首页/云/Docker 容器速查/Node 多阶段构建示例
镜像与构建107 条

Node 多阶段构建示例

Node 项目常见两段式:构建阶段装全量依赖编译前端,运行阶段只装生产依赖 + 拷贝构建产物。

Docker 容器速查云更新于 2026-10-13

Node 多阶段构建

Node 项目常用的两段式写法:构建阶段装全量依赖并编译,运行阶段只装生产依赖并复制构建产物。这样最终镜像里没有构建工具链与开发依赖,体积和攻击面都明显更小。

基本信息

阶段划分build 负责装全量依赖并编译,runtime 只装生产依赖
依赖安装两个阶段都需要复制 package.json 与锁文件
运行用户node 官方镜像自带 node 用户(UID 1000),可直接 USER node
环境变量运行阶段设 NODE_ENV=production
产物复制COPY --from=build /app/dist ./dist

典型使用场景

  • 前端项目:构建阶段跑打包命令,运行阶段只提供静态文件或 SSR 服务
  • 后端服务:构建阶段编译 TypeScript,运行阶段只跑编译后的 JavaScript
  • 控制镜像体积,不把开发依赖与构建工具带进生产镜像
  • 配合分层缓存:依赖层稳定,改业务代码不会触发重新安装依赖
  • 排查生产依赖缺失:确认运行阶段确实执行了生产依赖安装
  • 统一多环境构建:同一份文件在 CI 与本地得到一致的产物

示例

示例
FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci                        # 全量依赖,包含构建工具
COPY . .
RUN npm run build                 # 产出 dist/

FROM node:20-alpine 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 --chown=node:node /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]

两个阶段的分工

内容构建阶段是否安装是否进入最终镜像
开发依赖与构建工具是否
生产依赖是是
源码是(作为编译输入)否,只复制产物
编译产物 dist不涉及是
依赖安装缓存是不需要写入镜像
先复制 package.json 与锁文件再执行安装,最后复制源码:改一行业务代码不会触发依赖整层重装,构建时间差别很明显。
两个阶段都要复制锁文件,运行阶段只装生产依赖时同样需要它锁版本,漏掉会安装失败或版本漂移。
运行阶段用 USER node 之前,记得给产物目录设置属主(--chown),否则非 root 进程可能写不了缓存与日志目录。

易错点

  • 直接 COPY . . 再执行安装,改任何源码都会让依赖层缓存失效,构建时间被拖长
  • 运行阶段漏掉 --omit=dev,把构建工具与测试框架一起打进生产镜像,体积与风险面同步上升
  • 只复制了 dist 而漏掉运行时需要的模板、静态资源或配置文件,容器起来就报文件不存在
  • 生产环境依赖 npm run 脚本启动,而脚本用到的工具在运行阶段没装,应当直接用 node 启动产物

数据来源与参考

  • Docker 官方文档:Multi-stage builds(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌