Docker 镜像瘦身与多阶段构建的实践总结
接手一个 Node.js 项目时,发现它的镜像高达 900MB,每次 CI 拉镜像都要等很久。排查后发现问题集中在两点:用了完整的重基础镜像,以及把构建依赖也打包进了最终镜像。用多阶段构建可以一并解决。
问题镜像长什么样
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/server.js"]
node:18 完整镜像本身就接近 900MB,且 node_modules 里的 devDependencies 也被保留了下来。
多阶段构建
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]
核心思路:在 builder 阶段完成所有重活(安装依赖、编译),最终镜像只拷贝运行所需的 dist 和精简后的依赖。
继续瘦身
- 用
node:18-alpine替代完整版,体积立减八成 - 只拷贝
npm ci --production后的生产依赖 .dockerignore排除.git、node_modules、日志等- 合并 RUN 指令,减少镜像层数
RUN apk add --no-cache curl \
&& rm -rf /var/cache/apk/*
收益
优化后镜像从 900MB 降到 120MB,CI 构建和部署时间缩短了约 70%。更重要的是,攻击面也大幅缩小——镜像里不再有编译工具链和测试文件。
小结
多阶段构建是 Docker 最值得掌握的技巧之一。它把「构建环境」和「运行环境」彻底分离,让你鱼和熊掌兼得。