Introduction
A Dockerfile is a document that contains all the instructions to build an image. Basically, you create an image on top of the existing image with given specifications on the Dockerfile. Then Docker will take this file and follow your instructions to create a brand new image on top of the base image.
A base image is an image built by other users. Usually, the base image is a fundamental OS image. For example alpine
or ubuntu
. The base image gives you a base that you can instruct. Usually, we install our custom packages on top of the base image. However, we need multiple base images based on different needs.
Prerequisites
docker
What is multi-stage
Say that you have Go
project and you need to build it. For this case, you will need some packages only required for the build itself we do not want to keep these packages in our image just for build purposes.
Multi-stage Image Example
That is the reason that we need to use multi-stage to reduce our image size. Let’s create an image for an example:
FROM golang:1.17-alpine3.14 AS builderWORKDIR /appCOPY ./ /appRUN apk update && \
apk add ca-certificates gettext git make curl unzip && \
rm -rf /tmp/* && \
rm -rf /var/cache/apk/* && \
rm -rf /var/tmp/*
RUN go build -o my-binary main.go
In this Dockerfile
example, we are building main.go
file to binary. As you can see we are installing a bunch of other packages for building purposes but we do not need them for later usage of the image. This Dockerfile
creates an image sized 572MB
.
Let’s improve the Dockerfile
to adapt it to use multi-stage.
FROM golang:1.17-alpine3.14 AS builderWORKDIR /appCOPY ./ /appRUN apk update && \
apk add ca-certificates gettext git make curl unzip && \
rm -rf /tmp/* && \
rm -rf /var/cache/apk/* && \
rm -rf /var/tmp/*
RUN go build -o my-binary main.goFROM alpine:3.14COPY --from=builder /app/my-binary /bin/my-binaryENTRYPOINT ["my-binary"]
We added another FROM
which creates another stage with base image alpine
and copies the binary from the previous stage called builder
and put it to /bin/my-binary
path.
The new image size with multi-stage Dockerfile
is 7.36MB
. So, we only get the binary from the previous stage called builder
the other packages that we installed for building the binary is not included in our final stage.
Conclusion
We install lots of other packages on the base image to build staff. But, we do not always need those packages in the final image. Multi-stage Dockerfile
helps us to reduce the image size dramatically from 572MB
to 7.36MB
.
Originally published at https://omegion.dev/2022/03/how-to-create-multi-stage-dockerfile/.