Spring Boot 项目 Dockerfile 调整优化备忘 —— Could not find or load main class PropertiesLauncher

status
Published
type
Post
slug
spring-boot-3.2-dockerfile-change
date
Oct 10, 2024
tags
Docker
Java
Spring
Note
summary
文章说明了 Spring Boot 3.2 版本将 PropertiesLauncher 和 JarLauncher 类移至org.springframework.boot.loader.launch 包。这影响了使用解压 fat JAR 方式构建 Docker 镜像的 Dockerfile,需更新 ENTRYPOINT 命令中的类路径。java -jar 启动方式不受影响。建议利用 Spring Boot 分层 JAR 特性和 Docker 多阶段构建优化镜像,并记得关注 Release Notes 以便跟进相应变更。

TLDR

从 Spring Boot 3.2 版本开始,PropertiesLauncher 或者JarLauncher 这两个类的位置发生了变化,它们现在被统一放在了原路径下新定义的 launch 包下,即:org.springframework.boot.loader.launch.PropertiesLauncher
因此,之前编写的 Dockerfile 中也需要相应地更新这一引用,以避免出现 Could not find or load main class org.springframework.boot.loader.PropertiesLauncher 的错误 。
当然如果之前并没有在 Dockerfile 中将初步编译的 fat JAR 解压提取的操作,那这个问题就不会出现,毕竟 java -jar 的启动命令一般还是不会有变化的。(大概

Spring Boot 项目 Dockerfile 编写

简单 Dockerfile 示例

一个简单的 Dockerfile 如下即可:
考虑到 Docker 镜像分层的的特性,而 Spring Boot 构建得到的 fat JAR 本身也是有层次的,可以调整 Dockerfile 至如下:
现在即分成了三层,应用资源在后两层。如果依赖关系没变,那么第一层(/BOOT-INF/lib)就不需要变动,可以直接利用缓存机制加快构建速度以及运行启动速度。

Spring Boot 的分层 JAR 文件

自 Spring Boot 2.3 版本开始,使用 Spring Boot Maven 或 Gradle 插件构建的 JAR 文件中就包含了分层信息。这些分层信息将应用程序的不同部分根据它们在应用程序构建之间可能发生变化的可能性进行分离。基于这一特性可以使得 Docker 镜像分层更加高效。
利用这一特性,我们可以优化 Dockerfile,使得构建过程更加快速,同时生成的 Docker 镜像也更小。这对于频繁更新和部署的微服务应用尤其有益。一个示例如下:
JarLauncher 已从 fat JAR 中提取出来,可直接拿来用于启动应用程序,而无需像上面一样使用主函数名称硬编码作为应用启动入口。
这次遇到的问题也就在于此处作为启动入口的 JarLauncher/PropertiesLauncher 位置发生了变化。还是要多注意 Release 信息啊!

多阶段构建 Dockerfile 示例

利用 Docker 的多阶段构建特性,最终的 Dockerfile 示例如下:
当然还可以将 Maven 或 Gradle 构建的过程也加入到多阶段构建中,此处就不做展开了。
 

参考引用

 

2024 © HK