Multi-stage builds tách build environment khỏi runtime image — production image chỉ chứa built artifacts và prod deps, không có compiler/devDeps; từ ~1GB xuống ~150MB với node-alpine.
- Multi-stage builds dùng nhiều FROM statements để tách build environment khỏi runtime image — production image không chứa build tools, source code, dev dependencies.
- Node.js example: stage 1 (builder): FROM node:20 AS builder; COPY package*.json ./; RUN npm ci; COPY . .; RUN npm run build — compile TypeScript, bundle assets.
- Stage 2 (runtime): FROM node:20-alpine AS runtime; COPY --from=builder /app/dist ./dist; COPY --from=builder /app/node_modules ./node_modules; USER node; CMD ['node', 'dist/server.js'] — chỉ copy artifacts cần thiết, alpine image (~5MB vs ~900MB full node).
- Image size reduction: từ 1GB (node:20 với dev deps + source + build tools) xuống 150MB (node:20-alpine với chỉ production deps + built artifacts).
- Security benefits: attack surface giảm vì không có build tools (TypeScript compiler, webpack, etc.) trong production image — ít potential vulnerabilities hơn.
- Build arguments: ARG NODE_ENV=production cho phép customize behavior per stage — ARG có thể truyền từ docker build --build-arg.
- Named stages với AS: có thể copy từ specific stage bằng tên — COPY --from=builder; có thể build đến specific stage: docker build --target builder để debug build issues.
Multi-stage builds separate the build environment from the runtime image — the production image contains only built artifacts and prod deps, no compiler or devDeps; reduces from ~1GB to ~150MB with node-alpine.
- Multi-stage builds use multiple FROM statements to separate the build environment from the runtime image — the production image does not contain build tools, source code, or dev dependencies.
- Node.js example: Stage 1 (builder): FROM node:20 AS builder; COPY package*.json ./; RUN npm ci; COPY . .; RUN npm run build — compiles TypeScript and bundles assets.
- Stage 2 (runtime): FROM node:20-alpine AS runtime; COPY --from=builder /app/dist ./dist; COPY --from=builder /app/node_modules ./node_modules; USER node; CMD ['node', 'dist/server.js'] — only copies necessary artifacts; the alpine image is ~5 MB vs ~900 MB for the full node image.
- Image size reduction: from 1 GB (node:20 with dev deps + source + build tools) down to 150 MB (node:20-alpine with only production deps + built artifacts).
- Security benefits: reduced attack surface because build tools (TypeScript compiler, webpack, etc.) are absent from the production image — fewer potential vulnerabilities.
- Build arguments: ARG NODE_ENV=production allows customizing behavior per stage — ARG values can be passed via docker build --build-arg.
- Named stages with AS: copy from a specific stage by name — COPY --from=builder; build up to a specific stage: docker build --target builder to debug build issues.