Docker Compose — Multi-Stage in Compose

1 minute read

Multi-stage Dockerfiles produce small, secure production images. Compose makes it easy to target different stages for different environments.

Multi-Stage Dockerfile

# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]

# Stage 3: Development
FROM node:20-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

Targeting Stages in Compose

services:
  api:
    build:
      context: ./api
      target: production      # Use the 'production' stage
    ports:
      - "3000:3000"

Multiple Profiles for Different Stages

services:
  api-prod:
    build:
      context: ./api
      target: production
    ports:
      - "3000:3000"
    profiles: ["prod"]

  api-dev:
    build:
      context: ./api
      target: development
    ports:
      - "3000:3000"
    volumes:
      - ./api:/app
    profiles: ["dev"]
docker compose --profile dev up     # Development stage
docker compose --profile prod up    # Production stage

Size Comparison

┌──────────────────────────────────────┐
│  Without multi-stage:                │
│    node:20 + sources + devDeps       │
│    → ~900 MB                         │
│                                      │
│  With multi-stage (production):      │
│    node:20-alpine + dist + prodDeps  │
│    → ~150 MB                         │
└──────────────────────────────────────┘

Override Target for Development

compose.yml (production default):

services:
  api:
    build:
      context: ./api
      target: production

compose.override.yml (development override):

services:
  api:
    build:
      target: development
    volumes:
      - ./api:/app

Summary

Feature Detail
target: Select Dockerfile stage
Production Final stage, minimal image
Development Full tools, source mounted
Override compose.override.yml for dev
Profiles Different services per environment

Quick Reference

Item Detail
target: Select a Dockerfile stage
AS builder Named stages in Dockerfile
COPY –from=builder Copy artifacts between stages
Production Minimal final stage
Development Full tooling stage
Override compose.override.yml for dev target