JIB-CLI uses outdated classname in entrypoint when dockerzing a Spring-Boot-3.2 executable JAR.
Environment:
- Jib version: 0.12.1-SNAPSHOT (code base from Jan 24, 2024)
- Build tool: jib-cli, in JAR mode, with a Spring-Boot-3.2 executable "fat" jar
- OS: Linux and Windows, error occurs on both
Description of the issue:
Our backend is Spring Boot based. We're building executable JAR files with the "spring-boot-maven-plugin" and its "repackage" goal.
Afterwards, we're dockerizing these JARs with jib-cli.
Example command: jib jar --target ${TARGET_IMAGE} ${APP_JAR} --from ${BASE_IMAGE} ...
After upgrading from Spring Boot 3.1 to Spring Boot 3.2 we encountered the following problem with the Docker images created by jib-cli: Their entrypoint statements refer to an outdated Java class name.
Current, wrong entrypoint: "java", "-cp", "/app", "org.springframework.boot.loader.JarLauncher"
Running the Docker image fails with a very short error output, that contains a ClassNotFoundException.
The launcher class org.springframework.boot.loader.JarLauncher is not found in the JAR.
Problem analysis:
With Spring Boot 3.2, the "JarLauncher" class moved to a different package. Its fully-qualified class name is now org.springframework.boot.loader.launch.JarLauncher (Please note the new .launch. naming part).
In Jib cli's class SpringBootExplodedProcessor, the old Launcher class name is hard-coded in its method computeEntrypoint. See here
Solution proposal: The "SpringBootExplodedProcessor" should read the class to use in the image's entrypoint from the JAR file's MANIFEST.MF file (attribute main-class). That is, it should work like Jib's class "StandardExplodedProcessor" already does. Its method "computeEntrypoint" already evaluates the JAR's manifest.
Expected behavior:
We expected Jib to use the same class in the Docker image's entrypoint as defined in the Main-Class attribute in the file META-INF/MANIFEST.MF, which is located inside the to-be-dockerized JAR file.
As we built our JAR based on Spring Boot 3.2.2 and used Spring Boot's Maven Plugin (goal 'repackage') we expected that class to be org.springframework.boot.loader.launch.JarLauncher.
But it's org.springframework.boot.loader.JarLauncher instead.
Steps to reproduce:
-
Create a minimal Spring Boot application. Go to https://start.spring.io, let an app be created with
- Build tool: Maven
- Build tool: Java
- Spring Boot version: 3.2.2
- Packaging: JAR
- Java: 17
- Dependencies: none
-
Download the generated project's code and build it with the command
mvn package -
Navigate to the generated fat-jar. Its path might be demo/target/demo-0.0.1-SNAPSHOT.jar (depending on the app name you chose in step 1).
-
Unpack the JAR, navigate to its
META-INF/MANIFEST.MFfile, open that file and look at itsMain-Classattribute. Its value isorg.springframework.boot.loader.launch.JarLauncher. -
Use jib-cli to dockerize that JAR. Example command:
jib jar --target target-image-tag:v0.1 demo-0.0.1-SNAPSHOT.jar --from base-image-tag:v0.1 -
Inspect the generated Docker image with "docker inspect". You'll find the image's entrypoint to contain a different class name than the one detected in step 4.:
"Entrypoint": [
"java",
"-cp",
"/app",
"org.springframework.boot.loader.JarLauncher"
],
Additional Information:
I already fixed the problem in my local version of jib's code base and the fix solves the problem described above. I'll send a PR soon.
It turned out that Jib-cli's class StandardExplodedProcessor already uses the Main-Class from the JAR's manifest. So basically, I just had to copy its computeEntrypoint logic to the SpringBootExplodedProcessor class. Of course, I also extended SpringBootExplodedProcessor's unit test.
Thanks for bringing this up! However, as a workaround, I believe the jib cli command has a way to customize the entrypoint through this parameter.
Thanks @mpeddada1 for pointing out the workaround again. I was using the --entrypoint parameter wrong and tried it again now. Now I learned how to use it and it works fine for me :-) . We'll start using that parameter in our build process. By using the workaround, this issue is solved for me, but nonetheless adapting JIB to new Spring Boot versions would be a good idea.
Thank you for confirming that the workaround was able to help address your issue!