-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Add a slim version of the Corretto JDK 15 Docker images. #38
Conversation
JLink is used (retaining all modules) to create a slimmer version of the JDK excluding man-pages, header files and debugging symbols - saving ~113MB. Note that the objcopy linux tool is required for jlink to run, without which the error will occur: "java.io.IOException: Cannot run program “objcopy”: error=2, No such file or directory" Ref: https://command-not-found.com/objcopy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments on the Debian Dockerfile.
15/slim/debian/Dockerfile
Outdated
# | ||
# Slim: | ||
# JLink is used (retaining all modules) to create a slimmer version of the JDK excluding man-pages, header files and debugging symbols - saving ~113MB. | ||
RUN set -eux \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe your boolean ANDs obviates -e
usage. In my testing, the build fails with or without -e
when any command in the chain fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I also tested a failing command in the chain and saw the build fail.
&& apt-get update \ | ||
&& apt-get install -y --no-install-recommends \ | ||
curl ca-certificates gnupg software-properties-common fontconfig java-common \ | ||
&& curl -fL https://apt.corretto.aws/corretto.key | apt-key add - \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am aware that this is the official method recommended by Amazon however, this adds the key in manner which grants it validity over any software repository on the system, including those not distributed by Amazon. I understand this is quite pedantic but for illustrative purposes, the most correct and idiomatic way to add repositories on Debian is to add the following two apt config files:
/etc/apt/sources.list.d/apt.corretto.aws.list
/etc/apt/preferences.d/apt.corretto.aws.pref
And a gpg de-armored key (gpg --dearmor
) here: /usr/share/keyrings/apt.corretto.aws.gpg
.
apt.corretto.aws.list
can be created with:
echo 'deb [signed-by=/usr/share/keyrings/apt.corretto.aws.gpg] https://apt.corretto.aws stable main' | tee /etc/apt/sources.list.d/apt.corretto.aws.list
The contents of apt.corretto.aws.pref
should look like this:
Package: *
Pin: origin apt.corretto.aws
Pin-Priority: 1
Package: java-1.8.0-amazon-corretto-jdk
Pin: origin apt.corretto.aws
Pin-Priority: 500
Package: java-11-amazon-corretto-jdk
Pin: origin apt.corretto.aws
Pin-Priority: 500
Package: java-15-amazon-corretto-jdk
Pin: origin apt.corretto.aws
Pin-Priority: 500
This method also avoids pulling in software-properties-common
for apt-key
.
See:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
java-common
can probably be removed as well. This is pulled in automatically as a dependency to corretto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the unnecessary java-common apt-get install.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the apt-get install, I struggled with this one. Could I suggest that this update be made as a separate PR to both this slim Dockerfile and the regular JDK Dockerfile by someone with better expertise in the Debian OS?
I attempted to follow the instructions in the given reference documentation however saw errors with GPG validation during apt-get that I do not feel sufficiently well versed in Debian to address. I'm concerned that if I push through and implement something that I will inadvertently introduce bugs that would not be present using the standard install process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edited my comment for clarity and future reference but I think your comment makes perfect sense. This policy should really be reviewed for all of these Debian derived containers and updated in a separate PR along with a corresponding update to the official documentation.
15/slim/debian/Dockerfile
Outdated
&& mkdir -p /usr/share/man/man1 || true \ | ||
&& apt-get update \ | ||
&& apt-get install -y java-15-amazon-corretto-jdk=1:$version \ | ||
&& apt-get install -y binutils-i586-linux-gnu \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why binutils-i586-linux-gnu
and not binutils-i686-linux-gnu
or just binutils
? Also why isn't this grouped into the same invocation with the line above it? It could also be moved into the earlier apt-get install for clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point - grouped the install into the previous apt-get install, and used the more generic 'binutils' package.
As a benefit I no longer need to symbolic link the objcopy in the line below as binutils does this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more comments on the Debian Dockerfile after playing with it a bit more locally
15/slim/debian/Dockerfile
Outdated
curl ca-certificates gnupg software-properties-common fontconfig java-common \ | ||
&& curl -fL https://apt.corretto.aws/corretto.key | apt-key add - \ | ||
&& add-apt-repository 'deb https://apt.corretto.aws stable main' \ | ||
&& mkdir -p /usr/share/man/man1 || true \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|| true
is unnecessary here. -p
returns a zero exits status on failure to create the directory or intermediate path if it exists. (You wouldn't really want to hide this error even if it were necessary though...)
$ mkdir -p /tmp/test/it && mkdir -p /tmp/test/it
$ echo $?
0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
15/slim/debian/Dockerfile
Outdated
&& apt-get update \ | ||
&& apt-get install -y java-15-amazon-corretto-jdk=1:$version \ | ||
&& apt-get install -y binutils-i586-linux-gnu \ | ||
&& ln -s /usr/bin/i686-linux-gnu-objcopy /usr/bin/objcopy \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my testing this is already symlink'd to the correct objcopy
. This may be unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:) saw that too after switching to binutils.
15/slim/debian/Dockerfile
Outdated
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ | ||
curl gnupg software-properties-common \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to move this to the end and include binutils
as well? Additionally, does it make sense to also: apt-get clean --assume-yes && rm -rf /var/lib/apt/lists/*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea. I moved to the end and added binutils to the removed packages.
Removing binutils reduced the final image size by 15MB (from 268MB to 253MB).
15/slim/debian/Dockerfile
Outdated
&& for line in $(java --list-modules); do echo -n "${line%@15}," >> modules-comma-separated.txt; done \ | ||
&& jlink --add-modules "$(cat modules-comma-separated.txt)" --no-man-pages --no-header-files --strip-debug --output /opt/corretto-slim \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be rewritten as the following single line without any temporary files:
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-slim
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Much cleaner. Also handles the newer minor version suffixes :). Updated on the other Dockerfiles as well.
Forgot to mention, thanks for your effort here @luketn 😃. Since it will be used by many as a base image, I just want to make sure it's the highest possible quality before it gets merged. |
… jlink to build slim JDK)
…bstitution using sed and tr.
Thanks for the awesome review @joshenders! I've updated based on all of the comments, addressing all the issues with the exception of the GPG apt-get change which is a bit beyond my Debian skills. If you do merge this PR, would you also add to the automation code to build and publish these new Dockerfiles to DockerHub? I'm happy to help make changes there too if needed, but felt that might be outside of the scope of a new contributor. |
@joshenders - the review also managed to reduce the size of the image further as well (due to uninstalling binutils at the end - good thinking!). I also pushed all three Linux flavours to my personal DockerHub in case you'd like to see what the finished images would look like: |
@luketn and @joshenders Thanks for working on this! Do you intend to add a slim version of the JDK 11 images also? |
There actually already was a JDK 11 'JRE' Dockerfile in this repo (only for Alpine Linux). It appears not to have been published to DockerHub though. I think it would be great if we could agree on a standard approach for a slim/jre build of all Corretto 11+ distributions on all Linux flavours. |
Thank you for your feedback @luketn and @joshenders, We appreciate the interest in Corretto Slim images for Corretto-11 and above. However, The approach of using JLink was something that was previously discouraged by Dockerhub team.. The recommendation by joshenders is also valuable and we would like to incorporate this into the debian based docker images. If you have a Pull Request for that Please feel free to submit the same. |
@cliveverghese I read through the comments by Dockerhub team. I think you're referring to this comment?:
The comment from the Dockerhub team doesn't seem to be counselling against creating a slim/JRE build - only proposing to expand it beyond just being a docker image to being an official separate package. I can't comment whether that would be a possibility, however I think that the size of the Corretto JDK package and the size of the Corretto docker image have different implications. Since Docker uses layered image caching, you couldn't use the full Corretto JDK as a base image to construct a slim/JRE image. You would essentially have to start over and build from a base Linux image. The Dockerhub team acknowledge this in the next comment they make:
I think a compact version of the Corretto docker image would have a major impact on the Corretto JDK community. It would save a huge volume of unnecessary bytes being copied from disk into memory and over the network millions of times over. My personal use-case as an example:
With the slim docker image we could save 45% of the Corretto layer, reducing it from 307MB to 170MB. I could imagine a huge number of use-cases like mine which could benefit from a smaller distribution size. If there is a possibility of reducing the size, either through this PR's approach or through another approach, I'd urge you to consider it. |
We understand the use case and are would like to merge the changes, However, would you consider the following changes to the pull request before proceeding
|
Thanks @cliveverghese - that's awesome! Re: the two points:
This is a little complex. I tried doing this (just swapping rm for yum remove), but it breaks the image. At the moment, we install the JDK with yum and then swap out the JDK directory with the jlink'd version. All the other configuration done by yum stays in place. However, when I tried removing the package with yum, the system loses the configured java context so java is no longer on the path and configured with alternatives etc... I could go through the yum installer and replicate whatever it was doing by hand if needed - otherwise would you consider leaving it as-is? To be honest I'm not sure what else yum / apt does when the JDK installer runs - it might not be much - I'll look into it.
Done. I've run the GitHub actions workflows on my fork and they are all passing. See results here: |
@cliveverghese - further on point 1:
I took a look at the RPM and DEB package builds in the corretto-jdk repository. It looks as though the post install scripts use the alternatives command to register Java symbolic links in /usr/bin: I think we could register the new jlink'd slim JDK directory with alternatives / update-alternatives again after removing the original installed Corretto JDK. This would also have the advantage of not setting man pages which don't exist any more following the jlink too - these would otherwise be dangling symbolic links. I'll have a go at replicating these alternatives scripts in the Dockerfile for each OS. |
.github/workflows/verify-images.yml
Outdated
@@ -8,13 +8,20 @@ jobs: | |||
runs-on: ubuntu-latest | |||
strategy: | |||
matrix: | |||
version: [8, 11, 15] | |||
version-package: [8-jdk, 11-jdk, 15-jdk, 15-slim] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version: [8,11,15]
package: [jdk]
include:
- version: 15
package: [slim]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I've included the JRE 8 verification using the same include syntax, which cleans up the build a bit more too.
echo "${SHA_SUM} /etc/apk/keys/amazoncorretto.rsa.pub" | sha256sum -c - && \ | ||
echo "https://apk.corretto.aws" >> /etc/apk/repositories && \ | ||
apk add --no-cache amazon-corretto-15=$version-r0 binutils && \ | ||
/usr/lib/jvm/default-jvm/bin/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-slim && \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WARNING: Using incubator modules: jdk.incubator.foreign, jdk.incubator.jpackage
Should these be filtered out? Incubating features must be opted into with the compiler, so it seems like they should also be opted into for your runtime image.
/usr/lib/jvm/default-jvm/bin/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-slim && \ | |
/usr/lib/jvm/default-jvm/bin/jlink --add-modules "$(java --list-modules | grep -v incubator | sed -e 's/@[0-9].*$/,/' | tr -d \\n)" --no-man-pages --no-header-files --strip-debug --output /opt/corretto-slim && \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend keeping these incubator modules in the slim JDK image. They are in the full JDK image too and I don't think they do any harm to the runtime of applications which do not use them. I could imagine some use-cases for them, particularly the foreign memory mapping one. I think one of the benefits of keeping all modules is that we're not imposing any opinion on what should or shouldn't be included in the JDK - only reducing the size by omitting files required only at development time.
Issue #34
Description of changes:
Add a slim version of the Corretto JDK 15 Docker images.
JLink is used (retaining all modules) to create a slimmer version of the JDK excluding man-pages, header files and debugging symbols.
The size saved is significant:
Uncompressed:

Alpine Linux: 175 MB (183 MB smaller)
Amazon Linux 2: 357 MB (113 MB smaller)

The compressed sizes when pushed to DockerHub are pretty good too.
Alpine Linux: 58 MB (140 MB smaller)
Amazon Linux 2: 123 MB (83 MB smaller)
Ref:

https://hub.docker.com/r/luketn/amazoncorretto/tags
https://hub.docker.com/_/amazoncorretto?tab=tags&page=1&name=15-al&ordering=last_updated
Note that the objcopy linux tool is required for jlink to run, without which the error will occur:
"java.io.IOException: Cannot run program “objcopy”: error=2, No such file or directory"
Ref: https://command-not-found.com/objcopy
Also note I have not attempted to update any of the Travis build files - only the proposed new Dockerfiles are added with this PR, meaning further work would be required to integrate them into the CI/CD pipeline.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.