多阶段构建可显著减小微服务镜像体积——第一阶段用完整工具链镜像编译打包,第二阶段切换极简运行镜像仅复制产物;java镜像可从600mb压至150mb内,go服务甚至可用scratch实现单二进制镜像。

多阶段构建是缩短微服务镜像分发耗时最直接有效的方式——它从源头剔除所有非运行必需内容,让最终镜像只保留启动和运行服务的最小文件集。
用两个阶段彻底分离构建与运行
第一阶段专注编译打包,用完整工具链镜像(如 maven:3.9、golang:1.22 或 node:20)拉取依赖、执行测试、生成产物(.jar、.so、dist/);第二阶段切换到极简运行镜像(如 eclipse-temurin:17-jre-jammy、alpine:latest 或 gcr.io/distroless/java17),仅 COPY --from=builder 复制产物,不安装任何额外软件。
- Java Spring Boot 示例:单阶段镜像常超 600MB,多阶段后可压至 150MB 以内
- Go 微服务:直接用
scratch作为第二阶段基础,最终镜像≈单个二进制文件( - Node.js 后端:构建阶段用
node:20,运行阶段用node:20-alpine+COPY --from=builder /app/dist ./
避免跨阶段污染,确保“干净交付”
第二阶段不能出现 RUN apt-get install 或 npm install 类指令——所有依赖必须在第一阶段就完成安装并打包进产物,或显式 COPY 进来。否则不仅体积反弹,还可能引入不一致的运行时环境。
- 禁止在第二阶段
COPY .整个源码目录 - 不要在第二阶段保留
node_modules、target/test-classes、src/、docs/ - 若需配置文件或证书,应单独
COPY,而非复制整个项目根目录
配合基础镜像选型放大瘦身效果
多阶段构建的价值会因第二阶段基础镜像选择而显著不同:
- 用
ubuntu:22.04(77MB)作运行镜像,仍比alpine:latest(5MB)大十几倍 - Java 微服务优先选
distroless/java17(约 80MB),比openjdk:17-jre(400MB+)小一半以上 - 确认兼容性:Alpine 使用 musl libc,部分 JNI 或 C 扩展需在 staging 环境验证
用 docker history 和 dive 验证瘦身结果
构建完成后立即检查分层构成,确认构建工具链未残留、中间产物已被剥离:
-
docker history your-service:latest查看每层大小,警惕 >50MB 的 RUN 层 -
dive your-service:latest逐层浏览文件系统,重点搜索/usr/lib/jvm、/opt/maven、/app/node_modules/.cache等典型冗余路径 - 若发现异常大层,回溯 Dockerfile 中对应
RUN指令,补上清理命令(如&& rm -rf /root/.m2)











