news 2026/4/18 3:44:37

Docker 镜像瘦身术:如何把 Spring Boot 镜像从 500MB 优化到 80MB?(多阶段构建实战)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker 镜像瘦身术:如何把 Spring Boot 镜像从 500MB 优化到 80MB?(多阶段构建实战)

🐘 前言:为什么你的镜像那么“胖”?

很多 Java 开发者的Dockerfile是这样写的:

# ❌ 错误示范:直接用完整的 JDK 镜像 FROM openjdk:17 COPY target/my-app.jar app.jar ENTRYPOINT ["java", "-jar", "/app.jar"]

打完包一看:580MB
为什么?因为你打包了:

  1. 完整的 JDK(javac, jdb 等开发工具,生产环境根本不需要)。
  2. 笨重的 OS(Debian/Ubuntu,包含大量无用库)。
  3. Maven 缓存(如果你在镜像里执行了 mvn package)。

今天,我们用三个步骤,把这个数字变成80MB


🔪 第一刀:换个“底座” (JRE vs JDK)

生产环境只需要运行 Java 程序,不需要编译它。
所以,请把JDK换成JRE(Java Runtime Environment)。
更进一步,把操作系统从Debian换成Alpine Linux(一个只有 5MB 大小的 Linux 发行版)。

  • OpenJDK 17 (Debian): ~400MB
  • Eclipse-Temurin 17 JRE (Alpine): ~50MB

仅仅换个 Base Image,体积就减小了 350MB!


🏗️ 第二刀:多阶段构建 (Multi-stage Builds)

这是 Docker 的杀手锏。
想象一下做饭:

  • 阶段一(厨房):锅碗瓢盆、油烟机、案板(Maven, JDK, 源码)。乱糟糟的。
  • 阶段二(餐厅):只有一盘做好的菜(Jar 包)和一副餐具(JRE)。干干净净。

我们只把“餐厅”打包给用户。

原理流程图:

阶段二: 运行环境 (Runner)
阶段一: 编译环境 (Builder)
COPY --from=builder
Alpine JRE (极简 OS)
最终镜像
Maven 构建工具
Java 源码
生成 JAR 包

🚀 终极实战:完美 Dockerfile 模板

结合多阶段构建+Alpine JRE+分层构建 (Layered Jar),这是目前 Spring Boot 的最佳实践。

新建Dockerfile

# ============================ # 阶段 1: 编译构建 (Builder) # ============================ FROM maven:3.9-eclipse-temurin-17-alpine AS builder WORKDIR /build # 1. 单独拷贝 pom.xml 利用 Docker 缓存,避免每次都重新下载依赖 COPY pom.xml . # 预下载依赖 (这一步极大加速后续构建) RUN mvn dependency:go-offline # 2. 拷贝源码并打包 COPY src ./src RUN mvn clean package -DskipTests # 3. 提取 Spring Boot 分层 (为了更好的缓存支持) # 需要在 pom.xml 开启 layers 配置,或者直接用 java -Djarmode=layertools RUN java -Djarmode=layertools -jar target/*.jar extract # ============================ # 阶段 2: 生产运行 (Runner) # ============================ FROM eclipse-temurin:17-jre-alpine WORKDIR /app # 1. 也是分层 COPY,这样如果只是改了代码,依赖层(dependencies)不需要重新传输 COPY --from=builder /build/dependencies/ ./ COPY --from=builder /build/spring-boot-loader/ ./ COPY --from=builder /build/snapshot-dependencies/ ./ COPY --from=builder /build/application/ ./ # 2. 解决 Alpine 字体缺失问题 (验证码图片可能会用到) RUN apk add --no-cache fontconfig ttf-dejavu # 3. 启动命令 (使用 JarLauncher) ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

📊 效果对比:瘦身成绩单

我们来对比一下三种构建方式的最终镜像大小:

xychart-beta title "Docker 镜像大小对比 (MB)" x-axis ["原始方案 (JDK+Debian)", "仅换 Base (JRE+Alpine)", "多阶段构建 (最终版)"] y-axis "镜像体积 (MB)" 0 --> 600 bar [580, 150, 85]
  • 原始方案:580MB。包含完整的 OS 和 JDK,传输慢,安全漏洞多。
  • 最终方案:85MB。极致精简,秒级拉取,攻击面极小。

📝 总结

做镜像优化不仅仅是为了“省空间”,更是为了:

  1. 更快的发布速度:80MB 的镜像推送到阿里云/AWS 仓库只需要几秒钟。
  2. 更强的安全性:Distroless 或 Alpine 去除了 curl、wget 等工具,黑客进来了也难以下载脚本。
  3. 更低的成本:云厂商的镜像仓库存储和流量都是要钱的。

记住口诀:编译用 JDK,运行用 JRE,构建分阶段,底座选 Alpine。


博主留言:
你的镜像现在有多大?有没有遇到过Alpine 里的时区不对或者DNS 解析慢的坑?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 21:29:25

jQuery UI API 类别 - 方法(Methods)

jQuery UI API 类别 - 方法(Methods) Methods 是 jQuery UI API 文档中一个汇总类别,它列出了所有小部件(Widgets)共有的通用方法。由于 jQuery UI 的所有小部件都基于 Widget Factory(部件工厂&#xff0…

作者头像 李华
网站建设 2026/4/12 7:10:09

“零重写、少踩坑、快上线”——DBA小马哥亲历Oracle迁移到金仓迁移实战:一套兼容策略+三把自动化工具,让团队3天完成语法适配、2周交付生产库

大家好,我是DBA小马哥。今天要和大家分享的是一个非常实用的话题——如何从Oracle迁移到金仓数据库。作为一名资深数据库管理员,我经历过多次异构数据库的迁移项目,深知其中的技术挑战与实施难点。这次,我将结合一次真实的金融行业…

作者头像 李华
网站建设 2026/4/11 0:52:01

【开题答辩全过程】以 基于Java的电影推荐系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

作者头像 李华
网站建设 2026/4/16 7:59:45

Python - 发送电子邮件

用Python发送电子邮件 你可以用 Python 发送邮件,使用多个库,但最常见的是 smtplib 和 email。 Python 中的“smtplib”模块定义了一个 SMTP 客户端会话对象,可用于向任何带有 SMTP 或 ESMTP 监听器守护进程的互联网机器发送邮件。电子邮件…

作者头像 李华