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

Allow to use jib instance as base-image in multi-project builds #1807

Closed
remmeier opened this issue Jun 22, 2019 · 5 comments
Closed

Allow to use jib instance as base-image in multi-project builds #1807

remmeier opened this issue Jun 22, 2019 · 5 comments

Comments

@remmeier
Copy link

remmeier commented Jun 22, 2019

This is a follow-up on #1436 (Optimize Layering for Multi-Project Setups). In Gradle multi-project people typically build and deploy many (micro)services. Accordingly many Docker images are being built. In most cases those images will share a great amount of the techstack and only differ in the business functionality. Accordingly it would make sense to introduce a shared base layer holding third-party dependencies that are shared by all projects, whereas the individual projects only hold the delta to those base images. This could look like:

dependencies{
  compile project(':service-base')
  jibBaseImage project(':service-base')
}

whereas service-base holds all the third-party dependencies necessary for the various projects. This would trigger for a service project:

  • use of service-base as base layer of the Docker image (no need to specify one)
  • exclusion of all dependencies of :service-base in the built image.
  • check whether there is any dependency version mismatch whereas the service changes the version of a third-party library => services should not be able to overrule the version of the base image to avoid having the same JAR twice in the image.
  • the jibTasks like jib setup proper dependencies.
  • the jibTasks access the cache directory of the service-base to fetch the built artifacts.

The jib instance in service-base would be a regular jib instance.

Layering of Docker images has been discussed in other tickets like #403. While a simple/pragmatic solution has been implemented, it does fully address the brought up issues that desires to have more control of the layering. With this ticket here rather advanced layering can be setup transparently in a traditional "Gradle/Maven-way" without having to deal with inner workings of Docker layering or having to manually specify which third-party libraries go into which layer.

as a further benefit the multiple jib instances automatically will be "in-sync" in terms of caching, whereas the actual base layer (some JRE image) will only be downloaded once by service-base.

@chanseokoh
Copy link
Member

Is this different from #1778 and #1756? What are the differences? I think I got a vague picture, but with all these 3 issues, I really have hard time digesting all the information that touches a lot of aspects that all seem related but speak something slightly different. @loosebazooka may have understood all of these, but I don't really have great expertise in Gradle, so I think it would also help if you separate 1) what are the concrete changes necessary in Jib in a bit concise manner; and 2) the background/overview/rationale for the changes. And if you have multiple potential ideas for (1), it would help if you list them in a more clear way.

@remmeier
Copy link
Author

three very different tickets I would say. Seperating build from publishing is a general Gradle convetion (#1756) and is of importance in various areas like up-to-date checking. If one does #1778 one could start "hack" this ticket into jib manually without direct support (assuming that further classpath manipulation are added as well to add the JARs from the base image again).

Question would be whether there is a desire to support more advanced layering in Jib that go beyond more basic/single-project builds or whether project should move to the use of jib-core for custom builds or alternatives. There are various questions related to layering floating around, but a solution has been unclear as of yet. This here would be a proposal without having to go into the details of Docker.

I added a little example to the issue description how we currently consume/produce 750 MB rather than around 100 MB of layer data due to the lack of multi-project support, filling-up our Docker registries and slowing down the builds. So something in the area would be great to have. And I guess Gradle multi-project builds are quite common nowadays. I also refined the steps to implement it a bit in the issue description.

@loosebazooka
Copy link
Member

loosebazooka commented Jun 24, 2019

@remmeier Can you provide a more concrete example of what you're doing? It's not super clear on what you're trying to do that cannot be solved using current gradle mechanisms.

@remmeier
Copy link
Author

Our application looks like:

  • we have a Git repository with a single Gradle build building 30 (sub)projects
  • those projects build around 10 different REST services (and further init-containers)
  • the REST service have the same technology stack (Spring, Jackson, micrometer, crnk,...). Footprint of everything is quite substantial in terms of size.
  • given same technology stack we build with Jib 10 Docker images that look very much alike. The business functionality is different for each service, but third-party libraries like Spring are to 95% identical. But those other 5% cause for new third-party layers to be created for every one of those 10 Docker images. So it would be much much more efficient we were able to put the 95% into a seperate layer from those other 5%.
  • in Gradle we already have a "service-base" project where all the shared dependencies are defined.
  • as the simplest solution we guessed that being able to create a base image for "service-base" and then make us of that base image in all 10 other services we can achieve exactly with what we want and gain proper docker layering.
  • With a few further customization options that float around in other tickets, one could achieve this request here externally without touching Jib. But the problem seems quite generic, proper docker layering a frequent request and the result can bring large performance gains, so native support seems worthwhile to have.
  • once we are done building all the images we install them with Helm (https://github.com/rmee/gradle-plugins/tree/master/helm) in a subsequent deployment step.

Gradle up-to-date checking, caching, size of build artifacts and incremental updates of Kubernetes are one of our primary concerns/goals in the area to make it efficiently even tough the project is larger in size. We do not want to split up the project into many small parts and have to start versioning and manage them independently as it would drastically increase our efforts. Over the past months I created a number of tickets to make it work. It works in general, but the little things still hurt. This one being a primary one.

@JoeWang1127
Copy link

close as not planned

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

4 participants