Ý tưởng: stage build chứa toolchain, stage runtime chỉ chứa artifact.
Chỉ layer của stage cuối đi vào image xuất ra — mọi thứ ở stage trước (devDependency, compiler, source TS) bị bỏ lại.
dockerfile
FROM node:22-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]Các nguồn dung lượng bị cắt: devDependency (thường là phần lớn node_modules), cache npm, source code gốc, git history nếu lỡ COPY . ..
Với Go/Rust còn triệt để hơn — build ra binary tĩnh rồi copy vào scratch hoặc distroless, image xuống vài chục MB. Kèm theo phải có .dockerignore loại node_modules, .git, .env; nếu không, build context vẫn bị đẩy nguyên sang daemon.