0
0
DockerHow-ToBeginner · 3 min read

How to Reduce Docker Image Size Using Multi-Stage Builds

Use multi-stage builds in Docker by defining multiple FROM statements in your Dockerfile. Build your app in the first stage, then copy only the necessary files to a smaller base image in the final stage, reducing the final image size.
📐

Syntax

A multi-stage Dockerfile uses multiple FROM statements to create separate build stages. You can name stages with AS and copy artifacts between them using COPY --from=stage_name.

  • FROM base_image AS stage_name: starts a new build stage.
  • RUN: runs commands in that stage.
  • COPY --from=stage_name source destination: copies files from a previous stage.
dockerfile
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:3.18
COPY --from=builder /app/myapp /usr/local/bin/myapp
CMD ["myapp"]
💻

Example

This example shows a Go application built in a full Go environment, then copied into a small Alpine Linux image. The final image contains only the compiled binary, making it much smaller.

dockerfile
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:3.18
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/myapp /usr/local/bin/myapp
CMD ["myapp"]
Output
Successfully built image with only the compiled binary and minimal dependencies, reducing size from ~800MB to ~7MB
⚠️

Common Pitfalls

  • Copying unnecessary files from the build stage increases image size.
  • Not cleaning up build dependencies in the final stage can bloat the image.
  • Forgetting to install runtime dependencies (like certificates) in the final stage causes runtime errors.
dockerfile
### Wrong way: copying entire build context
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:3.18
COPY --from=builder /app /app
CMD ["/app/myapp"]

### Right way: copy only binary and needed files
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:3.18
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/myapp /usr/local/bin/myapp
CMD ["myapp"]
📊

Quick Reference

  • Use AS to name build stages.
  • Use COPY --from=stage_name to copy only needed files.
  • Choose a small base image for the final stage (e.g., Alpine).
  • Install only runtime dependencies in the final stage.
  • Keep build tools only in the build stage.

Key Takeaways

Multi-stage builds separate build and runtime environments to reduce image size.
Copy only necessary files from build stages to the final image.
Use small base images like Alpine for the final stage.
Install runtime dependencies only in the final stage to avoid bloat.
Avoid copying the entire build context to keep images lean.