Cloud Native 9 min read

How to Shrink Docker Images with Multi‑Stage Builds: A Step‑by‑Step Guide

Learn why smaller Docker images boost build speed and deployment efficiency, then master Docker’s multi‑stage build technique—including basic concepts, a Go example, layer reduction, cache optimization, minimal base images, non‑root users, and build arguments—to produce lightweight, secure, and maintainable containers.

Full-Stack DevOps & Kubernetes
Full-Stack DevOps & Kubernetes
Full-Stack DevOps & Kubernetes
How to Shrink Docker Images with Multi‑Stage Builds: A Step‑by‑Step Guide

Why Multi‑Stage Builds Matter

In containerized development, a smaller image means faster builds and deployments. Traditional Dockerfiles often bundle build tools and dependencies into the final image, inflating size, reducing security, and slowing CI pipelines.

1. Traditional Build vs. Multi‑Stage Build

Typical single‑stage Dockerfiles compile, package, and install dependencies all in one image, leading to:

Redundant dependencies that bloat the image.

Lower security due to unnecessary tools.

Reduced build efficiency because each run reinstalls everything.

Multi‑stage builds split the process into separate stages, copying only the final artifacts into a minimal runtime image.

2. Basic Multi‑Stage Build Example (Go Web App)

Source Code (main.go)

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, Docker Multi‑Stage Build!")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Dockerfile Using Multi‑Stage

FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o app

FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/app .
CMD ["./app"]

The first stage ( builder) compiles the binary with the full Go toolchain. The second stage uses a tiny alpine:latest image (≈5 MB) and copies only the compiled binary, discarding the build environment.

3. Advanced Optimizations

3️⃣ Reduce Layers & Optimize Cache

Each RUN, COPY, or ADD creates a new layer. Combine commands to cut layers, e.g.:

RUN apt‑get update && apt‑get install -y \
    curl \
    git && rm -rf /var/lib/apt/lists/*

Leverage Docker’s cache by copying immutable files (e.g., go.mod, go.sum) before the rest of the source:

COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o app

4️⃣ Use Smaller Base Images

Alpine : alpine:latest (~5 MB) is far smaller than ubuntu (~29 MB).

Distroless : gcr.io/distroless/static removes even more, leaving only the runtime.

FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o app

FROM gcr.io/distroless/static
COPY --from=builder /app/app /app
CMD ["/app"]

This can shrink the final image to under 5 MB.

5️⃣ Run as Non‑Root

Running as root poses security risks. Add a non‑root user in the final stage:

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

6️⃣ Parameterize Builds with ARG

Make Dockerfiles reusable by passing variables:

ARG GO_VERSION=1.21
FROM golang:${GO_VERSION} AS builder

Build with a specific version:

docker build --build-arg GO_VERSION=1.20 -t myapp .

4. Summary of Benefits

Reduced Image Size : Only runtime files remain, cutting megabytes.

Faster Builds : Layer caching and fewer layers speed up CI/CD pipelines.

Improved Security : Fewer packages and non‑root execution lower attack surface.

Better Maintainability : Build arguments and modular stages make Dockerfiles adaptable.

By adopting Docker multi‑stage builds, developers can keep the convenience of full‑featured build environments while delivering lean, secure, and fast‑to‑deploy container images.

Dockerimage-optimizationGoDevOpsContainer Securitymulti-stage-build
Full-Stack DevOps & Kubernetes
Written by

Full-Stack DevOps & Kubernetes

Focused on sharing DevOps, Kubernetes, Linux, Docker, Istio, microservices, Spring Cloud, Python, Go, databases, Nginx, Tomcat, cloud computing, and related technologies.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.