多阶段构建前端镜像的核心是彻底分离编译与运行环境:第一阶段用node:18-alpine等镜像安装依赖并执行npm run build生成dist;第二阶段用nginx:alpine仅COPY --from=builder /app/dist /usr/share/nginx/html/和自定义nginx.conf,确保最终镜像不含Node、源码、node_modules等任何构建残留。

用多阶段构建分离前端编译与运行环境,关键不是“用了几个阶段”,而是让构建工具链彻底不出现在最终镜像里。核心目标就一个:Nginx 容器里只放 dist/ 文件和配置,不带 Node、npm、源码、锁文件、node_modules。
明确划分两个阶段:构建 + 运行
第一阶段用含 Node 的镜像完成安装依赖和构建;第二阶段换用纯静态服务镜像(如 nginx:alpine)只复制产物。
- 构建阶段推荐
node:18-alpine或node:20-alpine:轻量、兼容性好、默认含 npm/pnpm - 运行阶段必须用
nginx:alpine(不用nginx:latest):基础层小、更新可控、无冗余包 - 避免在运行阶段执行任何
RUN指令安装东西——它不该有构建能力
精准复制 dist,杜绝路径污染
COPY --from=builder 是唯一允许把文件从构建阶段带入运行阶段的方式,但必须指定具体路径,不能宽泛拷贝整个工作目录。
- ✅ 正确写法:
COPY --from=builder /app/dist /usr/share/nginx/html/ - ❌ 错误写法:
COPY --from=builder /app .—— 会把src/、node_modules/、package.json全拖进来 - 若需覆盖 Nginx 默认配置,也应单独
COPY nginx.conf /etc/nginx/nginx.conf,不要混在源码里一起复制
优化缓存与构建确定性
CI 构建快不快,取决于 Docker 层是否能复用。把易变内容往后放,稳定内容往前放。
立即学习“前端免费学习笔记(深入)”;
- 先
COPY package-lock.json(或yarn.lock、pnpm-lock.yaml),再RUN npm ci --no-audit:锁文件不变时,依赖层永久缓存 - 再
COPY . .:源码改了才触发重新构建,不影响前面所有层 - 构建命令统一用
npm run build或pnpm build,禁用npm run serve类开发命令
运行时注入配置,避免硬编码
前端常需区分测试/生产 API 地址,但不能把敏感地址写死在构建产物里。
- 在 Nginx 启动前用
envsubst替换占位符,比如把API_BASE_URL=__API_BASE_URL__替换成实际值 - 或用 Nginx 的
sub_filter在响应中动态替换,配合location / { sub_filter ... } - 确保
nginx.conf中启用sub_filter_once off和sub_filter_types *;才能处理 JS/CSS


















