2.0.0 jib-maven-plugin breaking changes when using packaged containerizingMode.
daggerok opened this issue · 11 comments
Hello!
Environment:
- Jib version: 2.0.0
- Build tool: maven
- OS: MacOS 10.15.3
Description of the issue:
I'm using next multi-module maven configuration for fat jars in my root parent pom.xml:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>${jib-maven-plugin.version}</version>
<configuration>
<containerizingMode>packaged</containerizingMode>
<container>
<appRoot>/tmp</appRoot>
<entrypoint>
<shell>ash</shell>
<option>-c</option>
<arg>java -jar /tmp/classpath/*.jar</arg>
</entrypoint>
</container>
<from>
<image>openjdk:8u212-jre-alpine3.9</image>
</from>
<to>
<image>${docker-repository}/${project.parent.artifactId}-${project.artifactId}</image>
<tags>
<tag>${project.version}</tag>
<tag>latest</tag>
</tags>
</to>
</configuration>
</plugin>
and this configuration on 1.8.0 and 1.7.0 versions works well. But with 2.0.0 I'm getting error related to wrong jar file:
docker run --rm -it --name my-app daggerok/my-app
no main manifest attribute, in /tmp/classpath/app-1.0.0-SNAPSHOT.original.jar
Seems like previously (with versions: 1.7.0 or 1.8.0), generated by spring-boot maven plugin *.jar.original file wasn't copy, but since 2.0.0 it's for some reasons file app-1.0.0-SNAPSHOT.jar.original
now is copying as build artifact as app-1.0.0-SNAPSHOT.original.jar
or something else...
Expected behavior:
Application should start normally by picking right jar file: app-1.0.0-SNAPSHOT.jar
, not app-1.0.0-SNAPSHOT.original.jar
Steps to reproduce:
Just use provided jib maven plugin config for 1.7.0 or 1.8.0 versions to verify it works correctly.
Can you point me what I have to adjust to get same behaviour as with previous jib maven plugin versions?
Thanks in advice!
Regards,
Maksim
Hi,
This is the intended change. Don't define your own <entrypoint>
. It will most likely work out of the box, avoid using the dreaded fat JAR, and instead use the original one.
but I need fat jar and custom entrypoint for debugging purposes. using java-debugg image is inconvenient in our case
@daggerok could you explain more please? Also curious about where you're deploying to? We may be able to suggest alternatives to simplify your debugging requirements.
Hello @briandealwis
It's inconvenient because
- by jib opinionated way for debugging I should use these images
but it may be not enough by specific requirements or when we should be able to run our software in different number of containers OS, depends on customer needs. This is where it doesn't important efficient layering, jib can provide, but more important is ability to control image customisation - also I don't want to rebuilt my old tag (where for example bug was found) with gcr.io/distroless/java:8-debug image in in order to reproduce and debug reported bug, instead I would prefer just run previously published released tag which is already ready for debug.
for example, in comparison to what we've got with current jib, I would prefer to have entrypoint + cmd like this:so I can easily run app and attach to it and even completely override cmd / entrypoint on docker run. while with jib based images its not so flexible (I should rebuild with *-debug and doENTRYPOINT ["/bin/ash", "-c"] CMD ["java -jar ..."]
docker run --entrypoint=...
which is quite limited)
jib is super nice and I like it a lot, but sometimes current opinionated way can be quite limited or even cannot be applied at all... this is where It would be good to have more control and this is why for few customers we are using non standard customised fat jar as well (and btw even jib fat jar is much more better than custom Dockerfile builds...)
Regards,
Max
What's not clear to us is the requirement of a fat jar for debugging, perhaps we can solve this problem specifically: why do you need the fat jar to do the debugging?
As for some other things:
- You can use whatever image you want as the base image. Distroless is something we like to use, but it's just a suggestion. The difference between debug/non-debug images is the presence of certain tools (but has nothing to do with java - details)
Hello @loosebazooka
Thanks for feedback, but as I can see reported issue discussion is going in some wrong direction, related to debugging purposes, which was mention by me as first point goes in my mind, not as main reason why I need this configuration.
Anyway, in my first post I have provided example, which is working on 1.7.0 and 1.8.0, but doesn't work on 2.0.0... so maybe you can tell me if this is a bug or feature? Should be it possible do same with 2.x? Or not anymore due to some breaking changes or something?
What I can assume, with provided jib maven plugin configuration as result, it's picking *.jar.original file from target directory instead of *.jar. and renames it to *.original.jar file and then given command in args is failing...
Is it expected behaviour or something working wrong?
Thank you.
Regards
Right, the intention is to use packaged
as a jar + dependencies
style packaging, not a fat jar
packaging. So it's a feature? But I guess from your point of view, it is a change that breaks you (it was working in an undocumented way). https://github.com/GoogleContainerTools/jib/blob/master/jib-maven-plugin/CHANGELOG.md#fixed-1 (for 2.0.0 changes)
Moving forward, for your example to continue to work in 2.0.0, you might need to do something like(normally jib injects all this in, but given that you're using a custom entrypoint):
- <arg>java -jar /tmp/classpath/*.jar</arg>
+ <arg>java -cp /tmp/classpath/*:/tmp/libs/* my.package.MainClass</arg>
EDIT: corrected wildcard/paths in classpath
@daggerok the reason I'm probing about debugging is because you said:
but I need fat jar and custom entrypoint for debugging purposes. using java-debugg image is inconvenient in our case
If your setup it to enable JDWP so that you can connect a debugger, there's an alternative to using a custom startup script. You can configure the JVM for debugging with the JAVA_TOOL_OPTIONS
environment variable. For example, using Docker:
docker run -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,address=8000" -p 8000:8000 my-java-image
JAVA_TOOL_OPTIONS
is supported by all of the JVMs and this example will work irrespective of your base image.
Packaging a fatjar leads to poorer building and execution times. With a fat jar, a single source change results in rebuilding the fatjar, and so a new layer must be created and pushed. With Jib, we can just rebuild and push a new layer with just the .class and resource files, which is much faster. Most fatjars have to do some additional initialization and so are slower on startup. For modern web apps, which seem to have large numbers of dependencies, Jib's optimizations can make a large difference in both push and startup times.
Thank you all, just in case you want to try, to make it easier I have prepared steps for reproduce in a simple multi module spring boot project for jib configured to use far jar:
- clone repo:
git clone https://github.com/daggerok/github-jib-issue-2267
- build project for fat jar configuration using jib maven plugin version: 2.0.0 and then run docker container:
./mvnw -Djib-maven-plugin.version=2.0.0 docker run --rm -it daggerok/github-jib-issue-2267-app-2.0.0 # verify it doesn't work: find similar output: no main manifest attribute, in /tmp/classpath/app-0.0.1-SNAPSHOT.original.jar
- run same build but with version 1.8.0 this time and verify, everything is working as expected:
./mvnw -Djib-maven-plugin.version=1.8.0 docker run --rm -it daggerok/github-jib-issue-2267-app-1.8.0 # expected output..
Max
@daggerok correct, because it's intentionally not using the fatjar in 2.0.0 - you can try something like #2267 (comment)
In your test project specifically you would want to do
https://github.com/daggerok/github-jib-issue-2267/blob/master/pom.xml#L62
<arg>java -cp /tmp/classpath/*:/tmp/libs/* com.example.app.AppApplication</arg>
Got it.
Thanks