I'm a DevOps engineer evaluating base images for a Java 17 Docker application. I tried Eclipse Temurin JRE images based on Ubuntu Jammy and the default variant, but vulnerability scans reported a large number of findings. What alternatives would provide a smaller attack surface, and how should I distinguish genuinely exploitable issues from CVEs that are only present in unused OS packages?
5 Answers
Before switching images, triage the scan results. Many findings in the Ubuntu-based images belong to system packages that a Java process cannot reach, and scanners can report theoretical issues that are not exploitable in your application. Keep the image updated, scan your application dependencies too, and prioritize reachable, high-severity vulnerabilities rather than simply targeting a zero-CVE report.
Buildpacks or Jib can create optimized, layered Java images and make it easier to update the operating-system layers independently from the application. They are not automatically vulnerability-free, though—the underlying builder and runtime still need to be trusted and regularly updated. The main benefit is repeatable builds and simpler rebasing, not a guarantee of security.
If you control the application build, creating a custom runtime with jlink is another route. Include only the Java modules your application needs and start from a minimal or distroless base. This can reduce size and attack surface, but it adds maintenance and testing work, so it is not always worth doing just to lower a scanner count.
Distroless Java images are a good option if your application does not need a shell or package manager. They remove many OS utilities and packages, which reduces the attack surface and usually produces fewer findings. Make sure your logging, debugging, certificates, timezone data, and native-library requirements work with the more minimal environment.
Hardened Java images from vendors such as Red Hat, Chainguard, or BellSoft are worth evaluating if you need a supported update cadence and non-root or musl/glibc variants. Alpine can be small, but musl compatibility may matter for applications using native libraries. Whatever image you choose, rebuild frequently so newly disclosed operating-system and Java fixes are incorporated.

That does not eliminate the trust question; it moves it to the buildpack and its runtime stack. I would still pin versions, verify the source, and scan the resulting image.