多阶段构建是大型网站部署的标准实践,通过分离构建与运行环境,仅保留可执行文件或静态产物,显著减小镜像体积、提升安全性、加速CI/CD并支持多架构发布。

大型网站通常由前端(如 React/Vue/Angular)、后端(如 Java/Go/Node.js)和静态资源组成,部署时对镜像体积、启动速度、安全合规和 CI/CD 效率要求极高。Docker 多阶段构建不是“可选技巧”,而是这类场景下的标准实践。
明确分离构建与运行环境
大型网站的代码往往依赖重型工具链(Webpack、TypeScript 编译器、Maven、Go toolchain),但生产环境完全不需要它们。多阶段构建强制把编译、打包、压缩等动作关在“构建阶段”,最终镜像只保留可执行文件或静态产物,不带源码、lock 文件、dev 依赖、调试工具或凭证残留。
分层复用 + 阶段命名提升 CI 构建效率
比如一个含 Vue 前端 + Spring Boot 后端的网站,可设计为:
-
frontend-builder阶段:基于node:20-alpine安装依赖、执行npm run build,产出/dist -
backend-builder阶段:基于maven:3.9-openjdk-17打包 JAR,跳过测试(-DskipTests) -
nginx-runtime阶段:用nginx:alpine,COPY --from=frontend-builder /app/dist /usr/share/nginx/html -
java-runtime阶段:用eclipse-jre:17-jre-slim,COPY --from=backend-builder /app/target/*.jar app.jar
这样每个阶段独立缓存,前端改了只重跑 frontend-builder;后端改了不影响前端镜像构建。CI 中还可通过 --target frontend-builder 单独构建并推送前端镜像,实现前后端解耦发布。
规避敏感信息泄露的关键控制点
大型网站常需在构建中注入 API 密钥、内部域名或证书。多阶段构建配合 --build-arg 和 ARG 指令,可让密钥仅存在于构建阶段内存中(不写入镜像层),且绝不进入最终镜像:
FROM node:20 AS frontend-builder ARG VUE_APP_API_BASE_URL ENV VUE_APP_API_BASE_URL=$VUE_APP_API_BASE_URL WORKDIR /app COPY package*.json . RUN npm ci COPY . . RUN npm run build # 环境变量在构建时注入,产物中固化,但无原始密钥 FROM nginx:alpine COPY --from=frontend-builder /app/dist /usr/share/nginx/html
注意:ARG 必须在 FROM 后声明才生效;敏感值不要用 ENV 写死,更不能 COPY .env 进最终镜像。
应对多架构与灰度发布的灵活复制
大型网站常需支持 arm64(云服务器)和 amd64(本地开发)。多阶段构建本身不解决跨平台,但可结合 --platform 和 --from 实现产物复用:
docker build --platform linux/amd64 -t mysite/web:amd64 . docker build --platform linux/arm64 -t mysite/web:arm64 .
两个命令共享同一份构建阶段输出(只要基础镜像支持对应平台),运行阶段再分别拉取对应架构的轻量 runtime 镜像。
避免常见陷阱
- 不要在一个阶段里混合前端+后端构建:职责不清、缓存污染、失败难定位
-
COPY --from的路径必须是构建阶段内真实存在的绝对路径,建议WORKDIR统一、路径显式 -
alpine镜像虽小,但某些 Node.js 原生模块(如 bcrypt)不兼容,生产环境优先选debian-slim或ubi-minimal - 最终镜像应设非 root 用户(
USER 1001),该操作必须放在最后阶段,且不能在构建阶段设置(否则影响编译)
本质上,多阶段构建在大型网站中不是“怎么用”的问题,而是“必须怎么组织”的工程规范——它把构建逻辑从“能跑”推向“可审计、可复现、可分割、可收敛”。


















