Multi-Stage Docker Builds

Learn how to create efficient, production-ready Docker images using multi-stage builds

Quick Navigation

Difficulty: 🟡 Intermediate
Estimated Time: 20-30 minutes
Prerequisites: Basic Docker knowledge, Understanding of Dockerfile syntax, Command line experience

What You'll Learn

This tutorial covers essential multi-stage build concepts and tools:

  • Multi-stage build concepts - Understanding the benefits and use cases
  • Build optimization - Reducing final image size significantly
  • Security improvements - Excluding build tools from production images
  • Practical examples - Real-world applications for different languages
  • Advanced techniques - Build arguments and multi-platform builds

Prerequisites

  • Basic Docker knowledge
  • Understanding of Dockerfile syntax
  • Command line experience

Introduction

Multi-stage builds are a powerful Docker feature that allows you to use multiple FROM statements in your Dockerfile. Each FROM statement starts a new stage of the build, and you can selectively copy artifacts from one stage to another. This results in smaller, more secure production images.

Why Use Multi-Stage Builds?

  • Smaller images - Exclude build tools and dependencies
  • Better security - Remove unnecessary packages and tools
  • Cleaner separation - Build environment vs. runtime environment
  • Easier maintenance - Single Dockerfile for entire build process

Step-by-Step Instructions

Step 1: Basic Multi-Stage Structure

Create a new directory and Dockerfile:

mkdir multi-stage-demo
cd multi-stage-demo
touch Dockerfile

Step 2: Create a Simple Multi-Stage Dockerfile

# Build stage
FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy source code
COPY . .

# Build the application
RUN npm run build

# Production stage
FROM nginx:alpine

# Copy built files from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html

# Expose port
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]

Step 3: Build and Test

# Build the image
docker build -t multi-stage-demo .

# Check image size
docker images multi-stage-demo

# Run the container
docker run -p 8080:80 multi-stage-demo

Step 4: Advanced Multi-Stage Example (Go Application)

# Build stage
FROM golang:1.21-alpine AS builder

# Install git and ca-certificates
RUN apk add --no-cache git ca-certificates

WORKDIR /go/src/app

# Copy go mod files
COPY go.mod go.sum ./

# Download dependencies
RUN go mod download

# Copy source code
COPY . .

# Build the application
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Production stage
FROM scratch

# Copy ca-certificates from builder
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# Copy binary from builder
COPY --from=builder /go/src/app/main /app/

EXPOSE 8080

CMD ["/app/main"]

Step 5: Python Multi-Stage Example

# Build stage
FROM python:3.11-slim AS builder

WORKDIR /app

# Install build dependencies
RUN apt-get update && apt-get install -y \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements
COPY requirements.txt .

# Install Python dependencies
RUN pip install --user -r requirements.txt

# Production stage
FROM python:3.11-slim

WORKDIR /app

# Copy Python packages from builder
COPY --from=builder /root/.local /root/.local

# Copy application code
COPY . .

# Make sure scripts in .local are usable
ENV PATH=/root/.local/bin:$PATH

EXPOSE 8000

CMD ["python", "app.py"]

Advanced Techniques

Using Build Arguments

# Build stage
FROM node:18-alpine AS builder

ARG NODE_ENV=production
ARG BUILD_VERSION=1.0.0

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

# Production stage
FROM nginx:alpine

ARG BUILD_VERSION
LABEL version=$BUILD_VERSION

COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Multi-Platform Builds

# Build stage
FROM --platform=$BUILDPLATFORM node:18-alpine AS builder

ARG TARGETPLATFORM
ARG BUILDPLATFORM
ARG TARGETOS
ARG TARGETARCH

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

# Production stage
FROM nginx:alpine

COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Performance Comparison

Build TypeImage SizeBuild TimeSecurity
Single-stage850MB2:30Medium
Multi-stage120MB3:15High
Scratch-based15MB4:00Very High

Troubleshooting

Common Issues and Solutions

Issue: Build stage artifacts not found

# Solution: Ensure correct stage name and path
COPY --from=builder /app/dist /usr/share/nginx/html

Issue: Large final image size

# Solution: Use .dockerignore and clean up in each stage
RUN rm -rf /var/cache/apk/* /tmp/*

Issue: Build context too large

# Solution: Create .dockerignore file
node_modules
.git
*.log
dist

Debugging Multi-Stage Builds

# Build specific stage
docker build --target builder -t debug-image .

# Run build stage for debugging
docker run -it debug-image /bin/sh

# Check intermediate layers
docker build --progress=plain .

Best Practices

Stage Naming

  • Use descriptive names: builder, tester, production
  • Avoid generic names like stage1, stage2

Dependency Management

  • Install only necessary packages in each stage
  • Use multi-stage to separate dev and prod dependencies

Security Considerations

  • Use minimal base images for production
  • Remove build tools and sensitive files
  • Scan final images for vulnerabilities

Optimization Tips

  • Order Dockerfile instructions from least to most frequently changing
  • Use .dockerignore to reduce build context
  • Leverage Docker layer caching

Conclusion

Multi-stage builds are essential for creating production-ready Docker images. They help you:

  • Reduce image size significantly
  • Improve security by excluding build tools
  • Maintain a single Dockerfile for your entire build process
  • Optimize for different environments (dev, test, prod)

Start implementing multi-stage builds in your projects today and experience the benefits of smaller, more secure Docker images!


Tags: #Docker #MultiStage #Builds #Optimization #Production #Efficiency