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

containerizingMode = 'packaged' does not work with Spring Boot in Gradle #1851

Closed
maxbrunet opened this issue Jul 16, 2019 · 12 comments · Fixed by #2178
Closed

containerizingMode = 'packaged' does not work with Spring Boot in Gradle #1851

maxbrunet opened this issue Jul 16, 2019 · 12 comments · Fixed by #2178
Milestone

Comments

@maxbrunet
Copy link

Hi there!

We build our SpringBoot application with a BootJar task (which inherits from Jar) in Graddle, and the new containerizingMode = 'packaged' feature hard-codes the task name to jar:

case PACKAGED:
// Add a JAR
Jar jarTask = (Jar) project.getTasks().findByName("jar");
javaContainerBuilder.addToClasspath(
jarTask.getDestinationDir().toPath().resolve(jarTask.getArchiveName()));
break;

Would it possible to have this name configurable?

Like:

jib {
	jarTaskName = 'bootJar'
}

(or pass the task object directly, or even explicitly the path to the jar file)

I have currently worked around that by pointing the attributes of jar to bootjar:

jar {
    enabled = false
    destinationDir = tasks.bootJar.getDestinationDir()
    archiveName = tasks.bootJar.getArchiveName()
}

I guess another alternative could be (not tested and I'd like not to have to rename my bootJar task):

task jar(type: BootJar) {
	...
}
@loosebazooka
Copy link
Member

The one issue, and I think @chanseokoh can confirm, is that this isn't support for fatJar types. It's just Jars with dependencies still added into the container separately.

@chanseokoh
Copy link
Member

chanseokoh commented Jul 16, 2019

Hmm... this sounds familiar. I wonder if we should do the same for bootJar as in #1786. But I'm not entirely sure if the interaction between jar and bootJar is same as war and bootWar.

But as @loosebazooka mentioned, you should avoid containerizing a fat JAR, as it results in duplicating dependencies.

So, I think this issue is basically a feature request to support containerizing a fat JAR.

@maxbrunet
Copy link
Author

Hi @loosebazooka, thank you for quick reply, I actually just opened another issue about that #1852, though it would be separate problems (If it's by design, both will be quickly closed I guess). I'm pretty new to building Java apps/Gradle, I'm probably missing some pieces.

@chanseokoh chanseokoh changed the title Allow custom Jar task with containerizingMode = 'packaged' Allow custom JAR task/path with containerizingMode = 'packaged' (also applies to WAR and Maven) Jul 18, 2019
@chanseokoh
Copy link
Member

@maxbrunet I am trying this now. But I just realized that even though your workaround makes Jib pick up the fat JAR that Spring Boot generates, the image doesn't actually work. The entrypoint Jib generates is java -cp /app/classpath/*:... your.MainClass, and because the Spring Boot fat JAR doesn't put classes under the standard /classes/your/MainClass inside the JAR, the java -cp ... command doesn't work. Did you manually override Jib's entrypoint to something else? Or, is your fat JAR created in a different way somehow?

@maxbrunet
Copy link
Author

Yes, I had overwritten the entrypoint with jib.container.entrypoint.

@chanseokoh
Copy link
Member

Are you doing java -jar <fat.jar>? What's the main reason to do java -jar (if it is not because it's the only way to make it work with the "packaged" mode)? And is there a reason that you must use a fat JAR instead of the original thin JAR (if Jib worked with the original JAR and did not require changing the entrypoint)?

I'm asking these questions because my plan to support the "package" mode for Spring Boot is to make Jib pick up the original JAR instead of the Spring Boot-generated fat JAR. This will jsut automatically work without requiring changing an entrypoint or anything; it will just use the original thin JAR and do java -cp.

@maxbrunet
Copy link
Author

Yes, I did java -jar only to make it work. But as you said, there's not point of using Jib to build a fat jar. So your plan sounds good. Thank you for your work.

@chanseokoh
Copy link
Member

chanseokoh commented Nov 25, 2019

@maxbrunet so the best workaround for you should be to enable the jar task to generate a normal (non-fat) JAR. The Spring Boot reference says

By default, when the bootJar or bootWar tasks are configured, the jar or war tasks are disabled. A project can be configured to build both an executable archive and a normal archive at the same time by enabling the jar or war task.

so enabling the jar task is clearly supported by Spring Boot.

jar {
  enabled  = true
}

But then jar and bootJar will write their respective JAR to the same location, so you'll need to give a classifier to either one. For example,

jar {
  enabled = true
  classifier = 'original'
}

or

jar {
  enabled = true
}
bootJar {
  classifier = 'boot'
}

Then Jib will make use of the normal JAR instead of the fat JAR. This will let you avoid duplicating dependencies packaged in the fat JAR. Also this does not require you to manually override the entrypoint to something like java -jar.

@chanseokoh
Copy link
Member

chanseokoh commented Dec 6, 2019

#2178 basically resolves this issue. In the next release, you won't need any special workaround and Jib will just work. In fact, Jib will automatically implement the workaround above (enabling the jar task, setting classifier = 'original', and use the normal thin JAR).

The issue title (which I renamed so at some past point) talks about a potential feature to allow specifying a custom JAR task or path. But re-evaluating the current state, I think the feature is unnecessary (even for other app frameworks). The real issue was that <containerizingMode>packaged didn't work with Spring Boot projects. I'll rename the title and close the issue.

We'll let you know once we have a new release out.

@chanseokoh chanseokoh changed the title Allow custom JAR task/path with containerizingMode = 'packaged' (also applies to WAR and Maven) containerizingMode = 'packaged' does not work with Spring Boot in Gradle Dec 6, 2019
@TadCordle
Copy link
Contributor

@maxbrunet We've released 2.0.0, which contains this fix!

@ffroliva
Copy link

Hi, I am getting this error in maven:

Execution default-cli of goal com.google.cloud.tools:jib-maven-plugin:2.7.0:dockerBuild failed:
packaged containerizing mode for WAR is not yet supported

Are you going to support WAR in package mode?

I am struggling to build an image that uses the spring-boot tomcat embedded container in a WAR package.

@chanseokoh
Copy link
Member

chanseokoh commented Dec 14, 2020

Are you going to support WAR in package mode?

We don't have a plan. Given #1802 (comment) and the priority, unfortunately I don't think we will work on it anytime soon. Also particularly for WAR, we don't want to promote the packaged mode, as a WAR embeds all the app dependency JARs and leads to a very inefficient image layering.

At the moment, you can remove <containerizingMode>packaged, which should normally work.

I am struggling to build an image that uses the spring-boot tomcat embedded container in a WAR package.

By the design of Jib, if your project has type <packaging>war, Jib will assume you want to deploy a WAR file to some external Servlet engine process; it will not start the spring-boot tomcat embedded Servlet engine. The only way use the embedded server is to change the type to <packaging>jar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants