Docker 多阶段构建
多阶段 Dockerfile 分离构建和运行时,生成小生产镜像。
容器进阶
为什么
多阶段构建一 Dockerfile 多 FROM — 构建阶段有所有开发依赖,最终阶段仅复制构建产物。镜像减小 10-100 倍。
Docker is used by 59% of professional developers per the Stack Overflow 2024 survey,Kubernetes 在生产中运行 60% 的容器化工作负载(CNCF 2024 调查)。容器编排通过声明式滚动发布将部署相关事故减少 35%。
何时使用
所有生产镜像用多阶段 — 更小、更安全、更快拉取。 简单静态站点跳过容器 — CDN + 静态导出更便宜更快。10 人以下团队避免 Kubernetes;运维开销不合理。
如何做
1. 构建阶段 — FROM node:20 AS build,全依赖
2. 构建 — RUN npm ci && npm run build
3. 运行时阶段 — FROM node:20-alpine,精简
4. 复制 — COPY --from=build /app/dist ./dist
5. 依赖 — COPY --from=build /app/node_modules ./
6. CMD — 运行构建应用
7. 验证 — docker images,比较大小
示例
# Dockerfile — 多阶段
FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]
# 构建并检查大小
docker build -t myapp .
docker images myapp # ~150MB vs ~1GB 单阶段
常见问题
- ⚠复制错阶段 — COPY --from=stage-name,确保名匹配 AS 子句
- ⚠最终含开发依赖 — 最终阶段 RUN npm ci --omit=dev,非全装
- ⚠环境间配置漂移 — 使用基础设施即代码(Terraform/Pulumi)保持 dev/staging/prod 一致
最佳实践
- ✓最终阶段用 alpine 或 distroless — 最小基础,最少漏洞
- ✓仅复制所需文件 — 最终不 COPY . .,复制特定 dist/ 或 build/
- ✓设置健康检查和优雅关闭 — 处理 SIGTERM 以在退出前排空进行中的请求