Back to roadmaps docker Course

Shrinking Images: Multi-Stage Build Configurations

To build modern applications (like Next.js or Go APIs), you need heavy compiler dependencies, linters, and SDK tools. However, keeping these build tools in your production image increases its size and introduces security vulnerabilities. Multi-stage builds solve this by separating the build environment from the runtime environment.


1. Multi-Stage Workflow

graph LR
    subgraph Stage 1: Build Environment
        A[FROM node:20 AS builder] --> B[COPY source & install devDependencies]
        B --> C[RUN npm run build]
    end
    subgraph Stage 2: Production Environment
        D[FROM node:20-alpine AS runner] --> E[COPY --from=builder dist/ files]
    end

2. Implementing Multi-Stage Dockerfiles

Here is how to configure a multi-stage Dockerfile for a React/Node application:

# ==========================================
# STAGE 1: The Builder Environment
# ==========================================
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build # Outputs production-ready files to /app/dist

# ==========================================
# STAGE 2: The Production Runtime Environment
# ==========================================
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production

# Copy only the compiled dist files from the builder stage
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json

# Install only production dependencies
RUN npm ci --only=production

EXPOSE 3000
CMD ["node", "dist/server.js"]

3. Comparing Image Sizes

Using multi-stage builds can reduce the size of your production images significantly:

  • Single Stage Image (with build SDKs and tests): ~950 MB.
  • Multi-Stage Image (with production runtime and static assets only): ~120 MB.
Published on Last updated: