How to build a project inside a Docker container
I wanted to participate in the Hacktoberfest 2018, but one thing kept worrying me. I had to download someone’s code from the Internet and run it on my machine. I don’t have time to review a vast project to check if nothing fishy happens while running tests.
Of course, I could choose to work only on well-known projects with many respected contributors. In this case, I could safely assume that there is no harmful code in the repository. What about other projects?
I decided that the best available option is building and testing the projects inside a Docker container. I did not want to copy the code to a Docker image and download all dependencies every time I want to run tests. So I needed a way to cache them between the runs.
I wanted to contribute to Scala projects, so I needed to run SBT inside Docker. I ended up with this Dockerfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 FROM openjdk:8-jre-alpine ENV SCALA_VERSION 2.12.7 ENV SBT_VERSION 1.2.3 RUN \ apk add bash && \ apk add --no-cache curl && \ cd /tmp && \ curl -fsSOL https://piccolo.link/sbt-$SBT_VERSION.tgz && \ tar -xvzf sbt-$SBT_VERSION.tgz && \ mv /tmp/sbt /usr/lib && \ rm /tmp/sbt-$SBT_VERSION.tgz && \ ln -s /usr/lib/sbt/bin/* /usr/local/bin && \ sbt sbtVersion
It downloads the necessary dependencies and SBT, extracts the files, removes redundant files and sets symbolic links to the sbt tools.
Almost good. Such a Dockerfile runs the code as the root user. Still not a good idea, even inside Docker. So I added more code to Dockerfile:
1 2 3 4 5 RUN addgroup -g 12345 appuser && \ adduser -u 12345 -D -G appuser appuser USER appuser WORKDIR /home/appuser
Build the image
What now? Now I have to build the image and set its name to something meaningful, so later I can run it.
To build the Docker image you have to run the following command in terminal:
1 docker build -t sbt .
Run the container
When the image is ready, all I need is to run it in the interactive mode and mount the project directory as one of the directories in the Docker container. I must also mount the .ivy2 directory, so I have a place to cache dependencies between runs of the Docker image.
The next command does the job:
1 docker run -v $(pwd .):/home/appuser -v $(pwd .)/.packages:/home/appuser/.ivy2 -it sbt:latest
Now nothing stops me from contributing to someone else’s projects ;)