The Jib Gradle plugin is hard-coded to make use of the "main" classpath and "runtime" configuration. It should be possible to specify those two values in the JibExtension to allow customizations:
Many/most other Gradle plugins allow to do the same thing to maintain flexiblity of what gets touched by plugin. And effort for allowing that is minimal.
The ticket is related to https://github.com/GoogleContainerTools/jib/issues/894, but as requested created a ticket on its own. In most cases the changes requested here should be simpler and suffice for developers to allow doing customizations. The other ticket then would allow even more customization at expensve of additional complexity.
add further libraries to the classpath for Docker only
Can you explain this point a little more? It seems like you can either use the runtime scope or the extraDirectories option.
remove libraries from the classpath as they are already available in a base image.
This can be handled by the compileOnly or provided mechanisms?
change the source set because the projects main "purpose" is not being a docker image, but something else and have docker-related sources of the project in a non-main source set. We have that pattern quite frequently when we build plugins for other system that are then installed as initContainer. So the main artifact of the project would be the "plugin", whereas the initContainer is more a side-thing related to deployment. Currently we are forced to make setup two projects rather than just having two source sets.
I'm a little confused about this point. In reality it sounds like two projects IS what you want. They are separate artifacts and that are somewhat related.
I'm a little confused about this point. In reality it sounds like two projects IS what you want.
They are separate artifacts and that are somewhat related.
in this case the created images/initContainer are more of a build artifact rather than something warranting a project on its own. Examples where we have this for example are for Jenkins, Elastic and R3 Corda. We have around a dozen such projects and more coming. So what we would like to be possible to do is a Gradle plugin that takes that plugin project and jib and transparently setups an image/initContainer as part of the build. Important here are two things: the jib-related things cannot be on the runtime classpath and all logic to create the image can be put in a reusable fashion into a Gradle plugin.
add further libraries to the classpath for Docker only
Can you explain this point a little more? It seems like you can either use the runtime
scope or the extraDirectories option.
e.g. if you want to have a project both as RPM and Image. For either we end up with slightly different runtime classpaths. Goes a bit into a similar direction as above where one could have one rather than three projects.
remove libraries from the classpath as they are already available in a base image.
This can be handled by the compileOnly or provided mechanisms?
The baseImage is more of a Docker thing that should not leak into the Gradle runtime classpath. By using compileOnly we would loose the ability to make use of it outside of the Docker setting. But this is maybe more of another story, created https://github.com/GoogleContainerTools/jib/issues/1436 a while ago. But being able to fiddle around with sourceSets, configurations and classpaths could provide a good entrypoint into such topics, in particular since so far there seems no consensus how to approach the problem in a generic manner in jib (there are more tickets related to layering). There are a variety of different possiblities in achieving this and nothing may fit every use case. The current lack of support is quite noticable in the layering/size of your images and registry.
But this are just a few examples where one may would like to have a bit more flexilbity. I can imagine all kind of other use cases. The Jar, JavaExec, War, Test and most of the Java classpath-related Gradle tasks allow to set the Configuration for this reason. For sure not the default use case, more part of those other 5%...
I think that supporting custom source sets and configurations will be very useful. Otherwise, any Gradle project that uses these features cannot use jib. Exactly my case right now.
Please, provide these as jib's configuration options.
This can be handled by the
compileOnlyorprovidedmechanisms?
A really important use case which at least sounds to be related is developmentOnly() for example (because it should put those deps into a separate configuration, namely developmentOnly). I have this case with a spring app right now, where jib just packs reactor-tools and spring-boot-devtools into the container, which clearly do not belong there and it's also pretty much impossible to extract it into a different module because it's just a conditional addition for development purposes.
It basically seems like JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME should be made configurable here (change it to runtimeElements for spring for example):
https://github.com/GoogleContainerTools/jib/blob/27a949f63e61eb103dc47867e694c546c64d137f/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/GradleProjectProperties.java#L193
I may look into making a PR for that if it's easy to pull off.
@cromefire see the discussion in #2336 (which also includes a potential solution to the spring-boot-devtools issue). Basically, Maven/Gradle is the source of truth that defines which dependencies are required at runtime, and Jib just asks Maven/Gradle for the information. That said, it is the user's responsibility to set up Maven/Gradle dependencies correctly.
Just FYI, Jib has a general-purpose filtering extension (Maven / Gradle) that you can use to remove arbitrary files or move into other layers.
Basically, Maven is the source of truth that defines which dependencies are required at runtime
Well I'm using gradle in this instance, which has a different system, so maven profiles won't help here. If anything, configurations seem to be a similar thing to maven profiles in the use case. I think you may be confusing gradle and maven here, as there are no profiles in gradle.
That said, it is the user's responsibility to set up Maven dependencies correctly.
Well they are properly set up in a configuration so they can be properly excluded, there's just the lack of an option to tell the plugin to use the proper "non-dev" configuration
Just FYI, Jib has a general-purpose filtering extension (Maven / Gradle) that you can use to remove arbitrary files or move into other layers.
While this would probably technically be working, it would be a PITA to filter the files your self, if there's just an easy fix for it.
Sorry, I did mean to say Gradle instead of Maven. There's no difference between Gradle and Maven in this regard. (In #2336, you'll see that we have the Spring Boot extensions for both Maven and Gradle.)
There are multiple ways to have a profile-like behavior in Gradle. Perhaps an easy way is to use Gradle properties.
if (project.hasProperty('dev')) {
While this would probably technically be working, it would be a PITA to filter the files your self, if there's just an easy fix for it.
I agree using profiles is a much simpler way. I guess using a filter extension anyways requires you do use profiles. (BTW, just in case, the filtering extension is a different extension than the Spring Boot extension mentioned in #2336.)
There are multiple ways to have a profile-like behavior in Gradle. Perhaps an easy way is to use Gradle properties.
Actually @loosebazooka has more expertise in dependency configuration in Gradle and will have some opinions about setting up conditional dependencies in Gradle.
(In #2336, you'll see that we have the Spring Boot extensions for both Maven and Gradle.)
Okay I've missed that one, that seems to work for spring
There are multiple ways to have a profile-like behavior in Gradle. Perhaps an easy way is to use Gradle properties.
I don't see a point in point in duplicating things that are already in place here.
From the gradle docs:
A Configuration represents a group of artifacts and their dependencies.
Which seems to pretty much what you'd want in this case and also allows you to be more flexible than with properties
I may look into making a PR for that if it's easy to pull off.
I didn't really find the correct place where the dependencies are being resolved (yet, there's a lot of places where the project configurations and dependencies are mentioned), so sadly I wasn't able to get it working, so if somebody has a clue where that's happening, I can probably make it work
Well gradle holds two different references to the runtime classpath. One as a Configuration and one as a property on a SourceSet. We use both of these to determine how to arrange the final artifact. You're going to have to modify both of those somehow in GradleProjectProperties.java.
The problem with this approach is that if you consider the gradle application plugin simliar to the jib plugin, they both act on the main sourceset and the default runtimeClasspath. It's not clear to me how much special handling needs to be done to handle non-standard builds.
Even configuring custom Jars seems to requires some sort of manipulation of the underlying CopySpec.
It would be helpful to show an example of how another packager handles this? And and example of how you think the configuration should be surfaced.
Sure I can probably dig something up there but it'll probably take till the weekend sometime next week for me to get back to this
What we really need is an example of someone achieving this via another packager, like an example using Jar (which probably uses the underlying archive/copyspec constructs) or an example using Application plugin.
For instance, how would you fill this out?
sourceSets {
custom {
// what goes here that will result in how the packager fulfills its directive?
}
}
configurations {
customImplementation.extendsFrom implementation
customRuntime.extendsFrom runtime
}
I imagine for any packager to get this done correctly, either
sourceSets {
custom {
srcDirs sourceSets.main.java.srcDirs
}
}
// somewhere in jib config
sourceSets = ["main", "additional"]
So some samples I came across are the license plugin: https://github.com/hierynomus/license-gradle-plugin/pull/184
And the shadow jar plugin also seems to allow configurations: https://imperceptiblethoughts.com/shadow/configuration/dependencies/
I guess what I'm asking for is an example of how you've set up your configurations/sourcesets that would require this.
Jib can potentially accommodate to a point, but without a user correctly configuring things, we don't want to be a position of debugging someone's gradle build.
@remmeier @dmurat can you share some small example build with multiple source sets and how you expect things to be configured?
So basically I just have spring boot, where there is the extension, but that one only filters the dev tools and not all developmentOnly. To reproduce, basically start a new project at spring initializr and add something as developmentOnly()
Most helpful comment
I think that supporting custom source sets and configurations will be very useful. Otherwise, any Gradle project that uses these features cannot use jib. Exactly my case right now.
Please, provide these as jib's configuration options.