Multi-stage builds
Le multi-stage build résout un problème fondamental : les outils de compilation (compilateurs, SDK, dépendances de build) ne doivent pas se retrouver dans l'image de production. Sans multi-stage, on finit avec des images Go de 800 Mo pour un binaire de 15 Mo.
Principe
Un Dockerfile peut contenir plusieurs instructions FROM. Chaque FROM démarre un nouveau stage. On peut copier des fichiers entre stages avec COPY --from=. Seul le dernier stage (ou celui ciblé avec --target) compose l'image finale.
Exemple Go
# Stage de build
FROM golang:1.23-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/server ./cmd/server
# Image de production : scratch (vide) ou distroless
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/server"]L'image finale pèse quelques Mo et ne contient que le binaire et les libs système nécessaires. Aucun shell, aucun outil de build.
Exemple Node.js
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json .
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]Cibler un stage spécifique
# Build jusqu'au stage "builder" seulement (utile pour debug ou tests)
docker build --target builder -t app:debug .
# Build l'image de production complète
docker build -t app:latest .Stage de test intégré
FROM golang:1.23-alpine AS builder
WORKDIR /src
COPY . .
RUN go mod download
FROM builder AS test
RUN go test ./...
FROM builder AS release
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server
FROM gcr.io/distroless/static-debian12 AS production
COPY --from=release /app/server /server
ENTRYPOINT ["/server"]# Lancer les tests dans le pipeline
docker build --target test .
# Builder la prod seulement si les tests passent
docker build --target production -t app:latest .