Compile with a JDK in a build stage, then run on a JRE image in the final stage whenever your app does not need JDK tools at run time. A JRE image leaves out the compiler and diagnostic tools, which means fewer components to patch and fewer programs available after a compromise.
What differs between the two
A JDK includes the compiler, packaging tools and a range of diagnostic commands. A JRE is what you need to run compiled classes. The Eclipse Temurin official image page lists separate tag families for each, so the choice is a one word change in the tag, for example a jdk tag versus a jre tag, alongside the operating system variant such as Ubuntu, Alpine or UBI minimal.
| Final image | Contains | Good for |
|---|---|---|
| JDK | Compiler and tools | Build stage, rare run time needs |
| JRE | Runtime only | Most services |
| Custom jlink runtime | Only modules you use | Smallest runtime, you patch it |
| Distroless Java | Runtime, no shell | No shell access wanted |
The two stage pattern
FROM eclipse-temurin:21-jdk AS build
WORKDIR /src
COPY . .
RUN ./mvnw -q -DskipTests package
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /src/target/app.jar app.jar
USER 1000
ENTRYPOINT ["java", "-jar", "app.jar"]
Replace the tag with the Java line your team supports, and prefer pinning it more tightly, with a digest if your process can keep it fresh. The Docker Library page for the image publishes current tags, and it changes as new patch releases ship.
Reasons you might still need a JDK at run time
- A tool that compiles code on the fly, such as certain template or scripting engines.
- Attaching diagnostic tools to a running JVM for profiling, which some teams do on purpose in staging only.
- A framework that loads the Java compiler through the compiler API.
If you rely on one of these, confirm it before you switch, by running your integration tests against the JRE image. Do not discover it in production.
Security reasoning
Each extra program is something the next vulnerability scan will report and something an intruder can run. A JDK image carries more of both. Removing the unused part is cheap, since it is mostly a tag change. It does not replace dependency hygiene, because most findings in Java services come from libraries in the jar, not from the runtime image.
For the same reason, avoid copying the whole build directory into the final stage. Copy the one artifact you run.
Where Safeguard fits
Safeguard's dependency scanning reads your build files and the jar contents to produce an SBOM, and reachability analysis helps decide which library findings matter. Policies and gates can hold a pull request that adds a blocked component. The free scan gives a first dependency view for a Maven or Gradle project.
Quick check
Is a JRE image always smaller than a JDK image?
It usually has fewer tools, but size depends on the variant and operating system layer. Compare the actual tags you plan to use.
Does the JRE image protect me from vulnerable libraries in my jar?
No. Library findings are in your application dependencies, not in the runtime. Scan the jar or the lockfile separately.
Sources
Last reviewed: 19 October 2026.