多阶段构建的核心是分离编译与运行环境:第一阶段(builder)用maven:3.9-openjdk-17等完整镜像编译打包,第二阶段(runtime)仅用JRE或distroless镜像运行jar,最终镜像不含javac、mvn、src或pom.xml,体积可从1.2GB降至约200MB。

多阶段构建的核心是把“编译”和“运行”彻底分开——编译阶段用功能齐全的镜像干活,运行阶段只留最小必要环境,不带任何编译期组件。
明确两个阶段的分工
第一阶段(builder)负责编译打包,需要 Maven/Gradle + JDK;第二阶段(runtime)只运行 jar,只需 JRE 或更轻量的 Java 运行时。两者互不干扰,最终镜像里根本不存在 javac、mvn、src 目录或 pom.xml。
- builder 阶段用
maven:3.9-openjdk-17或gradle:8-jdk17,执行mvn clean package -DskipTests - runtime 阶段必须用
AS显式命名 builder,否则COPY --from=builder会失败 - 避免误用
openjdk:17-jdk-slim作基础镜像——它仍含完整 JDK,体积超 400MB
选对运行时基础镜像
精简不是越小越好,得兼顾可用性。JRE 镜像比 JDK 小一半以上,但还要看是否预装关键依赖。
-
amazoncorretto:17-jre-alpine:约 120–150MB,自带 ca-certificates,支持 TLS 和 DNS 解析 -
gcr.io/distroless/java17:仅约 15MB,无 shell、无 /bin/sh,适合高安全场景,但无法 exec 调试 - 别直接用
scratch:Java 应用依赖 glibc 和证书,硬切会报No such file or directory
优化 COPY 和中间产物
只拷贝真正需要的文件,同时清理构建过程产生的临时内容。
立即学习“Java免费学习笔记(深入)”;
- builder 阶段先
COPY pom.xml和src/,避免因COPY .带入 .git、IDE 配置等无用文件 - 打包后用
RUN mvn clean清理本地仓库缓存,减少层体积 - runtime 阶段只
COPY --from=builder /app/target/*.jar /app.jar,不复制任何其他路径
验证瘦身效果和运行稳定性
体积缩小不是终点,得确保应用能正常启动和对外服务。
- 构建后用
docker images对比大小,Spring Boot 项目常见从 1.2GB 降至 200MB 左右 - 运行容器后执行
docker exec -it <id> ls -l /,确认没有 /usr/lib/jvm/jdk-17、/root/.m2 等目录 - 检查日志是否有
NoClassDefFoundError或 DNS 失败,说明运行时镜像缺关键组件


















