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

Expose classpath, main class, and other variables for reference from an explicit entrypoint #894

Closed
briandealwis opened this issue Aug 28, 2018 · 17 comments

Comments

@briandealwis
Copy link
Member

Following on to #579 where it would be useful to be able to somehow reference the computed classpath from within an entrypoint definition.

For example, on Gradle:

jib {
  container {
    entrypoint = ['/opt/startup.sh', '-classpath', classpath.join(':'), '-jvmflags', '"' + jvmFlags.join(' ') + '"']
  }
}

Would we want users to be able to change the classpath?
Should we expose the computed main-class?

@remmeier
Copy link

remmeier commented Apr 9, 2019

in Gradle the correct behavior would be to set custom Configuration, e.g.

configurations {
    something
}

dependencies{
  something '...'
}

jib.configuration = configurations.something.

or with source sets like:

jib.sourceset = ...

The configuration can then be customized, inherited from other configurations, etc.

but have not seen something suggesting for this to currently be possibe. In GradleLayerConfigurations things is hardcoded to go for the main source set and its classpath. For our use case we would like to change that completely, not just extending it because the image is only a "by-product" of something else and currently we are forced to setup an additional project next to it to build the image.

@briandealwis
Copy link
Member Author

As I understand them, @remmeier, source-sets are for collecting groups of Java source files, whereas this PR is at least to simplify adding other jars or directories, for things like JVM agents, to the classpath in the container image. Which is not to say that supporting source-sets are not applicable. I'm a relative newbie to Gradle, so would you mind describing what you want to do, and why you want to do it that way?

@loosebazooka
Copy link
Member

@remmeier .. to further what @briandealwis said: we are just allowing further customization of the classpath part of the final entrypoint we generate for the container image.

@remmeier
Copy link

@briandealwis : sourceSets is not just about sources. It is also backed by configurations that specify how to compile and run the sources, like "test" sourcesets having "testCompile" and "testRuntime" configurations. Together they make up the application. That is what is used to do the packaging in Jib as far as I have seen in the GradleLayerConfigurations. So it would be a good step to make that configurable. This way one can influence what JARs get packaged and added to the classpath. That is probably sufficient for 95% of the classpath manipulation use cases.

Then there are of course other JVM things like adding agents, etc. That is something not covered by the sourcesets/configurations. JavaExecSpec might be a good inspiration for that area. Or may even make use of it.

@chanseokoh
Copy link
Member

chanseokoh commented Apr 10, 2019

@remmeier to further clarify @briandealwis' and @loosebazooka's point, this issue is about the potential capability for the users to add arbitrary paths to the runtime classpath of the image. These additional paths may not be the project-level or build-time Gradle classpath/dependencies or the path for Gradle sources. They may be completely independent of Gradle (such as /volume/dynamic). Looks like you are describing a different feature request. If so, could you create a new issue describing all the details? (Some of us are not Gradle experts, especially in idiomatic/best-practice usage).

@briandealwis
Copy link
Member Author

We're contemplating adding support for surefire-style @{property} resolving (e.g., @{jib.container.mainClass}). These properties would be expanded for the entrypoint, command arguments, and environment variables, allowing something like:

<container>
  <environment>
   <MAINCLASS>@{jib.container.mainClass}</MAINCLASS>
   <CLASSPATH>@{jib.container.classpath}</CLASSPATH>
  </environment>
</container>

@chanseokoh chanseokoh modified the milestones: v1.2.0, v1.3.0 May 6, 2019
@chanseokoh chanseokoh modified the milestones: v1.3.0, v1.4.0 Jun 10, 2019
@chanseokoh chanseokoh modified the milestones: v1.4.0, v1.5.0 Jul 18, 2019
@loosebazooka loosebazooka modified the milestones: v1.5.0, v1.6.0 Jul 18, 2019
@chanseokoh chanseokoh changed the title Expose classpath and other variables for reference from an explicit entrypoint Expose classpath, main class, and other variables for reference from an explicit entrypoint Jul 18, 2019
@chanseokoh
Copy link
Member

To clarify, properties like @{jib.container.mainClass} should be final value (e.g., possibly an inferred main class).

@leonard84
Copy link

What are the plans for this issue, the last comment was almost a year ago?

@chanseokoh
Copy link
Member

Unfortunately, about a year ago, we learned that it is a non-trivial undertaking to implement this due to our rigid config processing architecture, complicated with the fact that we need a common abstraction that should work for both Maven and Gradle.

It's almost certain that we will implement the Jib plugin extension framework far much sooner than working on this. (It's not even clear if this can ever be fixed at that point.) Once the extension framework is implemented, probably it may be easier to write an extension than fixing Jib to cover this issue.

@mfriedenhagen
Copy link

At least for our usecases, we want to set JAVA_OPTS in the Kubernetes configurations and want all processes to be wrapped in dumb-init resp. tini.

So I just created a small wrapper in /usr/local/bin/java (/usr/local/bin is in the PATH) like this:

#!/bin/sh -e
cd /srv
# DEFAULT_JAVA_OPTS may be extended with JAVA_OPTS
DEFAULT_JAVA_OPTS=${DEFAULT_JAVA_OPTS:--Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom -Djava.io.tmpdir=/tmp -Dnetworkaddress.cache.ttl=120 -XX:+UseContainerSupport}

exec /usr/bin/dumb-init -c -- /usr/bin/java $DEFAULT_JAVA_OPTS $JAVA_OPTS "$@"

What I would like to have is the possibility to redefine the executable "java" used by jib so that I may rename /usr/local/bin/java to /usr/local/bin/startup.

@chanseokoh
Copy link
Member

Unfortunately, about a year ago, we learned that it is a non-trivial undertaking to implement this due to our rigid config processing architecture, complicated with the fact that we need a common abstraction that should work for both Maven and Gradle.

It's almost certain that we will implement the Jib plugin extension framework far much sooner than working on this. (It's not even clear if this can ever be fixed at that point.) Once the extension framework is implemented, probably it may be easier to write an extension than fixing Jib to cover this issue.

As mentioned a while ago, this turned out to be a very tricky issue to support within Jib, and we hinted at implementing the Jib Extension Framework. The framework is now available with the latest Jib versions. With it, you can easily extend and tailor the Jib plugins behavior to your liking.

Thus, we think this issue can be best taken care of with an extension that rewrites an entrypoint. Extension code has access to Maven/Gradle API as well as the original Container Build Plan prepared by Jib, so someone might even be able to write a sufficiently general extension to resolve this issue. We appreciate anyone's contributions. At least it won't be difficult to write a small extension that is specific to your situation.

For general information about using and writing extensions, take a look at the Jib Extensions repo.

@remmeier @mfriedenhagen @leonard84 @dtreskunov @OneCricketeer @tellisnz-shift @seanabraham

@tomikmar
Copy link

We have a similar issue with our multi-module Maven project. For each module we have to explicitly define an entrypoint:

<entrypoint>/start.sh, com.abc.MyMainClassProvidedExplicitly</entrypoint>

Moving this to parent pom would simplify our config.

Maybe instead of exposing these variables (which seems to be hard) just add option to substitute them on request in an entrypoint string? For example we could use something like this in the parent pom

<entrypoint>/start.sh, mainClass</entrypoint>

and it would be changed to

<entrypoint>/start.sh, my-autodetected-main-class</entrypoint>

@chanseokoh
Copy link
Member

chanseokoh commented Jun 9, 2021

@remmeier @mfriedenhagen @leonard84 @dtreskunov @OneCricketeer @tellisnz-shift @seanabraham @tomikmar @flobjective

Previously we suggested an extension approach to the issue. With Jib 3.1.1 that we just released, we claim that the issue can be finally resolved with a reasonably good option.

Jib 3.1.1 creates two new JVM argument files inside an image, where they hold the computed classpath and the main class respectively. It will be trivial to retrieve these values from a shell. See the doc for more details.

@siwyd
Copy link

siwyd commented Jun 10, 2021

@chanseokoh Thanks, I believe I can get rid of our custom Jib extension now!

@mfriedenhagen
Copy link

🙌 @chanseokoh very useful, that will help tremendously with the shell script. Thanks a lot

@Dev-Loo
Copy link

Dev-Loo commented Jul 21, 2023

@chanseokoh would it be possible to list the expanded classpath (when a wildcard is used)? We are currently working in a model where we use wildcard and want to use expandClasspathDependencies to have a more predictable runtime when posting to different environments.
To do so we need to understand the expanded classpath currently in place and set that as the ENTRYPOINT.

@chanseokoh
Copy link
Member

@Dev-Loo I assume you are on Java 8, since there's nothing to worry or think about the classpath order on Java 9+.

would it be possible to list the expanded classpath (when a wildcard is used)? ... where we use wildcard and want to use expandClasspathDependencies

First of all, it is not Jib but a JVM that expands the wildcard, which can be implementation- and platform- dependent. Therefore, if possible, I recommend setting expandClasspathDependencies to not use a wildcard. And what you said doesn't make much sense to me, because as soon as you set expandClasspathDependencies, you don't use a wildcard.

Now, the documentation says that expandClasspathDependencies will be ignored when you set entrypoint yourself (probably someone should update the doc), but expandClasspathDependencies will still be effective about generating the /app/jib-classpath-file file. That is, the file will contain the enumerated list of dependency jars rather than libs/*. Check out the doc to get an idea of how you can utilize it when setting entrypoint yourself.

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

No branches or pull requests