Skip to main content
Omegion: Personal Blog Omegion
  1. Blog/

How to Create Multi-stage Dockerfile

·2 mins
Thumbnail

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 builder

WORKDIR /app

COPY ./ /app

RUN 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 builder

WORKDIR /app

COPY ./ /app

RUN 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

FROM alpine:3.14

COPY --from=builder /app/my-binary /bin/my-binary

ENTRYPOINT ["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.