Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIB-CLI uses outdated classname in entrypoint when dockerzing a Spring-Boot-3.2 executable JAR. #4175

Open
stefan-prange opened this issue Jan 26, 2024 · 0 comments · May be fixed by #4177
Open

Comments

@stefan-prange
Copy link

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:

  1. 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
  2. Download the generated project's code and build it with the command mvn package

  3. 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).

  4. Unpack the JAR, navigate to its META-INF/MANIFEST.MF file, open that file and look at its Main-Class attribute. Its value is org.springframework.boot.loader.launch.JarLauncher.

  5. 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

  6. 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.

stefan-prange added a commit to stefan-prange/jib that referenced this issue Jan 28, 2024
…s JAR's Main-Class when creating the target image's entrypoint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants