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

2.0.0 jib-maven-plugin breaking changes when using packaged containerizingMode. #2267

Closed
daggerok opened this issue Feb 6, 2020 · 11 comments

Comments

@daggerok
Copy link

daggerok commented Feb 6, 2020

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

@chanseokoh
Copy link
Member

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.

@daggerok
Copy link
Author

daggerok commented Feb 6, 2020

but I need fat jar and custom entrypoint for debugging purposes. using java-debugg image is inconvenient in our case

@briandealwis
Copy link
Member

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

@daggerok
Copy link
Author

daggerok commented Feb 6, 2020

Hello @briandealwis

It's inconvenient because

  • by jib opinionated way for debugging I should use these images
    image
    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:
    ENTRYPOINT ["/bin/ash", "-c"]
    CMD ["java -jar ..."]
    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 do 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

@loosebazooka
Copy link
Member

@daggerok

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)

@daggerok
Copy link
Author

daggerok commented Feb 6, 2020

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

@loosebazooka
Copy link
Member

loosebazooka commented Feb 6, 2020

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

@briandealwis
Copy link
Member

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

@daggerok
Copy link
Author

daggerok commented Feb 6, 2020

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

@loosebazooka
Copy link
Member

loosebazooka commented Feb 6, 2020

@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>

@daggerok
Copy link
Author

daggerok commented Feb 6, 2020

Got it.
Thanks

@daggerok daggerok closed this as completed Feb 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants