paketo-buildpacks/libjvm

Generate a custom JRE with jlink

Decat-SimonA opened this issue · 8 comments

Hello,

I'm not sure if this is the right repo to ask this... Is it possible to generate a custom JRE via jlink in order to get smaller docker image ?

It is not a common request, but @salmar expressed interest in contributing it. He'll have to comment on how far along that effort is.

Any update on this? I'm thinking along the lines of the plugin being able to use module-info.java files (if present) to create a docker image of a spring boot app which only contains the used JDK modules.

@Decat-SimonA I know it's been a long time, sorry. I think this is something we might be able to move forward with, but I'm trying to gather more feedback first. If this is something you're still interested in seeing, can you expand on how you'd see something like this working?

It would certainly be possible for the buildpack to run jlink as part of its build process. To run jlink we need some configuration though. What comes to my mind would be to start basic. We could make the buildpack provide a set of default arguments for jlink and allow the user to override those arguments.

For example, we could do something like this, where we include all modules but strip out man pages, header files and debug.

jlink --add-modules "$(java --list-modules | sed -e 's/@[0-9].*$/,/' | tr -d \\n)" --no-man-pages --no-header-files --strip-debug --output /opt/corretto

Alternatively, a user could override that default behavior by supplying their own list of modules.

At least initially, I think we would need to make this behavior off by default. If we get enough positive feedback, I could perhaps see us eventually enabling it by default.

Anyway, do you see this working for your use case? If not, can you expand on how you'd like to see this work?

@vab2048 - Same questions for you, but also can you expand on what you mean with regards to module-info.java files?

Thanks

I was pointed here, when I was trying to understand the size of images created by the Amazon Corretto buildpack. Since they don't release a JRE, there obviously needs to be a form of JDK in the run-image to run the compiled code, but I would like to have that JDK as minimal as possible (to reduce the size of the created image).

To that end, @dmikusa-pivotal, running jlink like that (as it's run by the Corretto project when creating a slimmer image) would definitely be great for that.

@dmikusa-pivotal apologies - what I wrote was not particularly clear.

Let me explain my use case...
Currently we can make docker images for our Spring Boot apps by using the Spring Boot plugin (for Maven/Gradle) and running the associated task (bootBuildImage with Gradle). Under the hood I am assuming this buildpack library is used. Currently it is common for the built docker images to be between 300mb and 500mb in size.

My point was that it would be desirable for the buildpack to be able to build 'slimmed down' Spring Boot docker images which only contain those Java modules which are actually used. Hopefully then the images built could be < 100mb in size.

What you are suggesting - using jlink to build the custom JRE and stripping out unnecessary files - is probably exactly what is needed.

Good luck!

OK, thanks for the feedback. I think that is probably good for us to start with an MVP for this feature. We can obviously iterate from there.

If anyone else has ideas or suggestions, free to add them here. Also, 👍 if you are looking for this feature.

There is some work we need to address before we can get to this particular issue, so I can't give a definite date. I'd say Jan/Feb of next year is a likely target. If you stay tuned to this issue I'll update as we're making progress.

jam01 commented

@dmikusa-pivotal any word on this by any chance? :)

It's on the roadmap. We definitely plan to implement. It's more of a timing issue. There are a few other projects in our queue first.

If someone were interested in submitting a PR, I could make time to merge that. It would need to be in libjvm. It would be something to add to the Contribute method, this is where we configure the JRE that ends up in the launch layer. We'd want to filter so that it only runs jlink if the j.DistributionType == JDKType, which limits it to run when a JDK is being used as a JRE. The buildpack would need to run jlink, basically like this, and handle arguments similar to this.