Docker Multi-Stage Builds: Reduce Your Container Image Size by 80%

Large Docker images slow down deployments, waste storage, and increase attack surface. Multi-stage builds are the solution. Learn how to dramatically reduce your container sizes.

The Problem with Single-Stage Builds

# Bad: 1.2GB image
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/index.js"]

This includes dev dependencies, source files, and build tools — none of which are needed at runtime.

Multi-Stage Build Solution

# Good: 150MB image
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --only=production
USER node
CMD ["node", "dist/index.js"]

Python Example

FROM python:3.12-slim AS builder
WORKDIR /app
RUN pip install --user --no-cache-dir -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "main.py"]

Go: The Ultimate Small Image

FROM golang:1.22 AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .

FROM scratch
COPY --from=builder /app/server /server
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
ENTRYPOINT ["/server"]

This produces images as small as 10-15MB!

Best Practices

  • Use -alpine or -slim base images
  • Order COPY commands from least to most frequently changed
  • Use .dockerignore to exclude unnecessary files
  • Run as non-root user with USER directive
  • Use npm ci instead of npm install for reproducible builds
  • Pin exact versions of base images

Size Comparison

Typical results with multi-stage builds:

  • Node.js app: 1.2GB → 150MB (87% reduction)
  • Python app: 900MB → 120MB (86% reduction)
  • Go app: 800MB → 12MB (98% reduction)

Conclusion

Multi-stage builds are a must for production Docker images. They reduce size, improve security, and speed up deployments. Start using them in every Dockerfile you write.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Privacy Policy · Contact · Sitemap

© 7Tech – Programming and Tech Tutorials