JRehkemper.de

Stages in Dockerfiles

If you want to compile your Program while building your Container but don’t want you source code to be part of your image, you need to use stages.

Why should I want that?

My biggest concern is, that your container image gets small if it does only contain the binary and not all of the source code and temporary file from building it. That helps with download and creation-speed.
On the other hand one might fear that his source code gets extracted if someone gets access to the image.

How to use it

In my example I am building a simple Go Application and my Dockerfile looks like this.

FROM golang:1.21-bullseye

ENV GOPATH=/app/dependencies

WORKDIR /app
COPY . .  

RUN go build

RUN chmod +x my-app

CMD /app/my-app

First of all we will add a name to the first phase right behind the FROM-Statement. Lets call it Build. That way we can reference it in the next phase.
We can also drop the CMD-Statement at bottom, since we will not run this container.

FROM golang:1.21-bullseye as build

ENV GOPATH=/app/dependencies

WORKDIR /app
COPY . .  

RUN go build

RUN chmod +x my-app

Next we will add our second phase below it. The great thing of multiple phases is, that i can use different images for different phases. In this case I will compile in a golang container and execute in an alpine container.

FROM golang:1.21-bullseye as build
ENV GOPATH=/app/dependencies
WORKDIR /app
COPY . .  
RUN go build

FROM alpine:3.10
# Go links to libc -> you need to install it
RUN apk add --no-cache libc6-compat 
WORKDIR /app
COPY --from=build /app/my-app /app/
RUN chmod +x /app/my-app
CMD /app/my-app

You can see that i reference the build phase in the COPY-Statement of the second phase. This way i can copy only the compiled binary from phase one.
I also moved the chmod to the second stage instead of the first.

Now we can build our image as usual.

docker build -t my-app:latest .  

After that we can use our Container-Image and it will only have the binary in it and not the whole source-code.

docker run my-app:latest
profile picture of the author

Jannik Rehkemper

I'm an professional Linux Administrator and Hobby Programmer. My training as an IT-Professional started in 2019 and ended in 2022. Since 2023 I'm working as an Linux Administrator.