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?

Docker

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.

User

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 ;)

Did you enjoy reading this article?
Would you like to learn more about software craft in data engineering and MLOps?

Subscribe to the newsletter or add this blog to your RSS reader (does anyone still use them?) to get a notification when I publish a new essay!

Newsletter

Do you enjoy reading my articles?
Subscribe to the newsletter if you don't want to miss the new content, business offers, and free training materials.

Bartosz Mikulski

Bartosz Mikulski

  • Data/MLOps engineer by day
  • DevRel/copywriter by night
  • Python and data engineering trainer
  • Conference speaker
  • Contributed a chapter to the book "97 Things Every Data Engineer Should Know"
  • Twitter: @mikulskibartosz
Newsletter

Do you enjoy reading my articles?
Subscribe to the newsletter if you don't want to miss the new content, business offers, and free training materials.