容器化Spring Boot应用很简单,但低效的Docker镜像会导致部署臃肿、启动缓慢和安全风险。
本文我们将使用多阶段构建、Spring Boot的Layer工具和类数据共享(CDS)来优化Docker镜像,将体积缩小达60%,启动时间减少30%。
为什么要优化Docker Layer?
• 更小的镜像:加速CI/CD流程并降低云存储成本
• 更快的启动:对无服务和自动扩展环境至关重要
• 安全性:通过排除构建时依赖来最小化攻击面
• 高效缓存:通过隔离频繁变更的代码来优化重建
1. 多阶段构建:分离构建与运行时
多阶段构建会从最终镜像中丢弃不必要的构建工具(如Maven、JDK)。
![null 图片[1]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区](https://static.didispace.com/images3/07bbb5520caf878bae65293121ecc313.png)
未优化的Dockerfile
FROM eclipse-temurin:22-jdk
COPY . /app
WORKDIR /app
RUN ./mvnw package
CMD ["java", "-jar", "target/app.jar"] # 镜像大小: ~890MB

使用多阶段优化后的Dockerfile
# 阶段1: 构建
FROM eclipse-temurin:22-jdk AS builder
COPY . /app
WORKDIR /app
RUN ./mvnw package -DskipTests
# 阶段2: 运行时
FROM eclipse-temurin:22-jre
COPY --from=builder /app/target/app.jar /app.jar
CMD ["java", "-jar", "/app.jar"] # 镜像大小: ~432MB (减少48.36%)
![null 图片[3]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区](https://static.didispace.com/images3/e50ebcf623d7ca5d8275b6060bd9600a.png)
![null 图片[4]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区](https://static.didispace.com/images3/3683e08a250429e8ee9a77ab33d566ec.png)
关键优势:
• 从最终镜像中移除了构建工具(Maven、JDK)
• 使用更小的JRE基础镜像而非JDK
2. Spring Boot Layer工具:分离依赖
虽然多阶段构建减小了镜像体积,但Spring Boot的Layer工具通过将依赖与应用程序代码分离进一步优化了缓存,最小化开发过程中的重建。layertools
模式将JAR分为:
1. dependencies:已发布的库(很少变化)
2. spring-boot-loader:Spring内部组件
3. snapshot-dependencies:SNAPSHOT库(偶尔变化)
4. application:您的代码(频繁变化)
步骤1:提取 layer
java -Djarmode=layertools -jar app.jar extract
步骤2:分层优化的 Dockerfile
# 阶段1: 构建
# --------------
FROM eclipse-temurin:22-jdk AS builder
COPY . /app
WORKDIR /app
RUN ./mvnw package -DskipTests
# 阶段2: 运行时
# ----------------
FROM eclipse-temurin:22-jre AS runtime
WORKDIR /app
ARG JAR_FILE=target/app.jar
COPY --from=builder ${JAR_FILE} app.jar
RUN java -Djarmode=layertools -jar app.jar extract
COPY --from=builder /app/dependencies/ ./dependencies/
COPY --from=builder /app/spring-boot-loader/ ./spring-boot-loader/
COPY --from=builder /app/snapshot-dependencies/ ./snapshot-dependencies/
COPY --from=builder /app/application/ ./application/
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
优势:
• 对application
层的更改不会使缓存的依赖失效
• 最终镜像:~300MB(额外减少33%)
3. 类数据共享(CDS):加速启动
类数据共享(CDS)通过将核心Java类预加载到共享存档中,减少JVM启动时间,避免JVM每次运行时重新解析这些类。
步骤1:生成CDS存档
运行应用一次以创建类列表和存档:
docker run --rm -v "$PWD":/app -w /app eclipse-temurin:22-jdk \
bash -c "java -XX:+UseAppCDS -XX:DumpLoadedClassList=classes.lst -jar app.jar && \
java -XX:+UseAppCDS -XX:SharedArchiveFile=app.jsa -XX:SharedClassListFile=classes.lst -jar app.jar"
**注意:**需要在受控环境中生成存档,因为这需要运行应用程序。
![null 图片[5]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区](https://static.didispace.com/images3/09fe8f1a3f71e7653561e324ad84a0fc.png)
步骤2:上传 Dockerfile
# 阶段 1: 构建
FROM eclipse-temurin:22-jdk AS builder
COPY . /app
WORKDIR /app
RUN ./mvnw package -DskipTests
# 阶段 2: 运行时
FROM eclipse-temurin:22-jre AS runtime
WORKDIR /app
COPY --from=builder /app/dependencies/ ./dependencies/
COPY --from=builder /app/spring-boot-loader/ ./spring-boot-loader/
COPY --from=builder /app/snapshot-dependencies/ ./snapshot-dependencies/
COPY --from=builder /app/application/ ./application/
COPY app.jsa .
ENTRYPOINT ["java", "-XX:SharedArchiveFile=app.jsa", "org.springframework.boot.loader.JarLauncher"]
结果:启动时间从2.1秒降至1.05秒(提速40%)
没有回复内容