Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区

Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度

 

容器化Spring Boot应用很简单,但低效的Docker镜像会导致部署臃肿、启动缓慢和安全风险。

本文我们将使用多阶段构建、Spring Boot的Layer工具和类数据共享(CDS)来优化Docker镜像,将体积缩小达60%,启动时间减少30%

为什么要优化Docker Layer?

• 更小的镜像:加速CI/CD流程并降低云存储成本

• 更快的启动:对无服务和自动扩展环境至关重要

• 安全性:通过排除构建时依赖来最小化攻击面

• 高效缓存:通过隔离频繁变更的代码来优化重建

1. 多阶段构建:分离构建与运行时

多阶段构建会从最终镜像中丢弃不必要的构建工具(如Maven、JDK)。

图片[1]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区

未优化的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%)
图片[3]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区
图片[4]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区

关键优势:

• 从最终镜像中移除了构建工具(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"

**注意:**需要在受控环境中生成存档,因为这需要运行应用程序。

图片[5]-Spring Boot的Docker Layer优化:缩小镜像体积并提升启动速度-Spring专区论坛-技术-SpringForAll社区

步骤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%)

 

请登录后发表评论

    没有回复内容