A Guide to Docker Multi-Stage Builds

An article regarding Multi-Stage Builds on Docker

Md Shamim
CodeX
3 min readDec 22, 2022

--

Photo by insung yoon on Unsplash

A Docker image is built up from a series of layers. Each layer represents an instruction in the image’s Dockerfile. Each layer except the very last one is read-only.

One of the most challenging things about building images is decreasing image size. In this article, we will discuss how we can optimize a docker image size.

Let’s create a custom docker image for a simple golang application.

# app.go

package main

import (
"fmt"
"time"
"os/user"
)

func main () {
user, err := user.Current()
if err != nil {
panic(err)
}

for {
fmt.Println("user: " + user.Username + " id: " + user.Uid)
time.Sleep(1 * time.Second)
}
}

Now, let’s write a Dockerfile to package the golang application :

# Dockerfile

FROM ubuntu # Base image
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y golang-go # Install golang
COPY app.go . # Copy source code
RUN CGO_ENABLED=0 go build app.go
CMD ["./app"]

Next, Create a docker image and run a container from that image :

# Create image from the Dockerfile
>> docker build -t goapp .
...
Successfully built 0f51e92fe409
Successfully tagged goapp:latest

# Run a container from the image created above
>> docker run -d goapp

04eb7e2f8dd2ade3723af386f80c61bdf6f5d9afe6671011b60f3a61756bdab6

Now, ‘exec’ into the container we created earlier :

# exec into the container
>> docker exec -it 04eb7e2f8dd sh

# list the files
~ ls
app app.go bin boot dev etc home ...

# run the application
~ ./app
user: root id: 0
user: root id: 0
user: root id: 0
user: root id: 0
user: root id: 0
...

We can see that after building the application we have appartifact inside the container. If we check the image size which helped us to build our application artifact :

>> docker images goapp

REPOSITORY TAG IMAGE ID CREATED SIZE
goapp latest 0f51e92fe409 16 hours ago 870MB

The image size is ‘870MB’, but we can slim this down using multi-stage builds. With multi-stage builds, we will use multiple FROM statements in our Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. We can selectively copy artifacts from one stage to another by leaving everything that we don’t want in the final image. To show how this works, let’s adapt the Dockerfile from the previous section to use multi-stage build.

We will divide our Dockerfile into two stages. One will be the build stage, which will help us to build our application and generate the artifact. And then we will only copy the artifact from the build stage to another stage and create a tiny production image.

# Dockerfile
# named this stage as builder ----------------------
FROM ubuntu AS builder
ARG DEBIAN_FRONTEND=noninteractive
# Install golang
RUN apt-get update && apt-get install -y golang-go
# Copy source code
COPY app.go .
RUN CGO_ENABLED=0 go build app.go

# new stage -------------------
FROM alpine
# Copy artifact from builder stage
COPY --from=builder /app .
CMD ["./app"]

Now, build the image and check the image size :

>> docker build -t goapp-prod  .

Successfully built 61627d74f8b8
Successfully tagged goapp-prod:latest

>> docker images goapp-prod

REPOSITORY TAG IMAGE ID CREATED SIZE
goapp-prod latest 61627d74f8b8 5 minutes ago 8.92MB # <---

As we can see image size has been reduced significantly. It’s time to check if we can run a container from the image we created.

# create docker container
>> docker run goapp-prod

user: root id: 0
user: root id: 0

Great! We were able to use the tiny production image we created and it is working perfectly.

If you found this article helpful, please hit the Follow 👉 and Clap 👏 buttons to help me write more articles like this.
Thank You 🖤

👉All Articles on Linux

All Articles on Linux

12 stories

👉All Articles on Kubernetes

All Articles on Kubernetes

23 stories

👉All Articles on Helm

HelmーSeries

11 stories

--

--

Md Shamim
CodeX

Cloud Infrastructure Engineer | AWS Community Builder | AWS | Kubernetes | GitHub Actions | Terraform | 👇👉 linkedin.com/in/shamimice03 github.com/shamimice03