Skip to content

Create a custom JRE for the Docker image#993

Open
toindev wants to merge 1 commit into
gaul:masterfrom
toindev:401_custom_docker_JRE
Open

Create a custom JRE for the Docker image#993
toindev wants to merge 1 commit into
gaul:masterfrom
toindev:401_custom_docker_JRE

Conversation

@toindev
Copy link
Copy Markdown

@toindev toindev commented Mar 1, 2026

Fixes #401

Improvement : reduces the attack surfaces on the Docker image (makes our automated tools scream less often).

Custom Java runtime creation:

  • Added a Maven exec-maven-plugin execution to run jdeps during the package phase, outputting the required Java modules to target/jdeps-modules.txt. This automates module dependency analysis for jlink.
  • Updated the Dockerfile to use a multi-stage build: the first stage creates a custom JRE with jlink using modules listed in jdeps-modules.txt, and the second stage builds the final runtime image
  • Added comments in the Dockerfile (helps with AI coding assistants)

CI/CD workflow:

  • Builds a custom stripped down JRE to run the tests, as close as possible to the one used in the Dockerfile (some extra modules are required by Maven).
  • Modified .github/workflows/ci-main.yml to upload and download the new jdeps-modules.txt and the jar-with-dependencies as build artifacts, ensuring these are available for the Docker build step.
  • Updated .dockerignore to allow target/jdeps-modules.txt into the Docker build context, so the custom JRE can be constructed from actual dependencies.

Build artifact:

  • Changed the assembly configuration to exclude module-info.class files from the jar-with-dependencies, preventing conflicts and unnecessary files in the runtime.

Docker build :

  • Kept ubuntu as a base for the final image, so as not to break any downstream build

@gaul
Copy link
Copy Markdown
Owner

gaul commented Apr 16, 2026

Sorry I missed this earlier -- could you resolve the conflicts?

@toindev toindev force-pushed the 401_custom_docker_JRE branch from f45c0bb to 9f55520 Compare May 5, 2026 07:50
@toindev
Copy link
Copy Markdown
Author

toindev commented May 5, 2026

Sorry I missed this earlier -- could you resolve the conflicts?

@gaul : 😄 I understand missing a notification on GH

@gaul
Copy link
Copy Markdown
Owner

gaul commented May 6, 2026

Thanks for tackling this! Good direction overall — jlink meaningfully reduces image size and attack surface. A few things to address before merge:

Should not be in this PR

  • .vscode/settings.json is personal IDE/Peacock theme config, unrelated to the JRE work. Please drop it (and consider adding .vscode/ to .gitignore). It also lacks a trailing newline.

Likely bugs / dead code

  • The s3proxy-jar artifact (jar-with-dependencies) is uploaded and downloaded to target/, but .dockerignore only allows target/s3proxy and target/jdeps-modules.txt into the Docker build context — so the jar never reaches the image. Either drop the upload/download or document why it's needed. target/s3proxy (appassembler) is what's actually copied.
  • RUN chmod +x /opt/s3proxy/run-docker-container.sh is redundant; the script is already 0755 in the repo and COPY preserves mode.

Drift / duplication

  • The CI jlink invocation and the Dockerfile jlink invocation have already diverged (CI adds jdk.compiler,jdk.zipfs,java.instrument,jdk.attach for Surefire). Consider just running tests on the full JDK to avoid drift — or factor the module list into a shared script. Otherwise these will desync silently over time.

Forward compatibility

  • --compress=2 is deprecated in JDK 21 and emits a warning. Prefer --compress=zip-6 (or zip-9) in both places.

Coverage gap

  • Nothing in CI runs the produced Docker image end-to-end. Since jdeps --ignore-missing-deps will silently skip modules used reflectively or via ServiceLoader, a smoke test that boots the container and hits an endpoint would catch missing-module regressions.

Minor

  • --bind-services pulls in service-provider modules transitively; usually desirable but worth confirming the resulting size vs. an explicit allowlist.
  • Stage 1 does a full apt-get update && install dumb-init just to copy one binary out — installing it in stage 2 (which already runs apt) would be more conventional.
  • The cp .../cacerts line is only needed if the source JDK's cacerts are newer than what java.base ships; a one-line comment on intent (or dropping it if unnecessary) would help.
  • "helps with AI coding assistants" comments are noise; prefer comments that explain non-obvious why.

Nice changes

  • Multi-stage Dockerfile, keeping Ubuntu base for downstream compatibility, deriving the module list from jdeps, and excluding module-info.class from the fat jar — all good.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate jlink to avoid bundling entire JDK

2 participants