多阶段构建的核心作用是让编译依赖“进得去、出不来”,即仅存在于构建阶段,完全不落入最终镜像;第一阶段专注构建,装全工具并执行编译产出dist,第二阶段仅保留运行必需文件,通过COPY --from精准复制产物,从设计上杜绝源码和devDependencies进入生产镜像。

多阶段构建的核心作用,就是让编译依赖“进得去、出不来”——它们只存在于构建阶段,完全不落入最终镜像。关键不是删掉什么,而是从设计上就不让它进去。
第一阶段:专注构建,装全所需工具
这一阶段要完整还原开发环境,确保能跑通 TypeScript 编译、Vite 构建、ESLint 检查等流程。它需要 devDependencies、完整 node_modules 和源码:
- 基础镜像选
node:20-slim或node:18-alpine,兼顾兼容性与体积 -
COPY package*.json ./放在最前,保证依赖安装层可缓存 -
RUN npm ci(而非 install),确保依赖树与 lock 文件严格一致 -
COPY . .放在依赖安装之后,避免代码变更导致重装 - 执行构建命令,如
RUN npm run build,产出dist/或build/
第二阶段:仅保留运行必需,彻底剥离编译痕迹
这个阶段的镜像里,不该出现任何与构建相关的东西:没有 src/、没有 .ts 或 .vue 文件、没有 tsconfig.json、没有 webpack.config.js,更没有 devDependencies。
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
- 用干净的基础镜像启动,例如
node:20-alpine - 只
COPY package*.json,然后RUN npm ci --only=production—— 这一步只装dependencies,devDependencies被天然过滤 - 用
COPY --from=builder /app/dist ./dist精准复制产物,不带任何源码或配置文件 - 若项目含原生模块(如 bcrypt),可在构建阶段用
node-prune清理冗余文件,再复制到生产镜像
进阶控制:防止意外泄露
即使结构正确,疏忽仍可能引入风险。几个容易被忽略但很关键的操作:
- 在
.dockerignore中明确排除src/、test/、.git、.env、node_modules/(避免本地模块被误 COPY) - 不要在生产阶段
COPY . .,这是最常见的泄露源头 - 避免使用
npm install,它会读取package.json并安装所有依赖(含 dev);始终用npm ci --only=production - 构建完成后,可用
docker run --rm <image> sh -c "ls -la | grep -E '(src|node_modules|.ts)'"快速验证是否残留
为什么不能靠“删”来隔离?
Docker 镜像是分层的,RUN rm -rf src/ 只是在新层标记“删了”,原始文件仍存在于底层镜像中,可通过 docker history 查看。真正安全的做法是——从一开始就不把它们 COPY 进来。多阶段构建的不可见性,才是彻底隔绝的根本保障。

















