How to Choose the Right Java Base Image, JDK/JRE, and Optimize Container Settings
This guide walks through selecting Alpine or Debian base images, deciding between JDK and JRE, picking Oracle or OpenJDK, choosing the appropriate JVM, handling graceful shutdown signals, configuring memory limits across JDK versions, managing DNS cache, and leveraging GraalVM native compilation for Java containers.
System Image Selection
For the base image, the three common choices are Alpine, Debian, and CentOS. CentOS is no longer stable, so choose between Alpine (smaller size but uses musl libc) and Debian (glibc compatibility). If your application heavily depends on glibc or JNI, prefer Debian; otherwise Alpine is fine.
JDK or JRE
JDK includes development tools ( javac, jps, jstack, jmap) and contains JRE; JRE is runtime only and smaller. Use JRE if you only run a jar, but for debugging or production issues, using JDK as the base image avoids extra steps.
JDK Choice
Choose Oracle JDK only if your code uses private Oracle APIs (e.g., com.sun.*). Otherwise OpenJDK is sufficient. Unused imports can be cleaned with IDE shortcuts (Option+Command+L, Control+Option+O).
OpenJDK Distributions
Popular OpenJDK builds include AdoptOpenJDK (now Eclipse Adoptium, image name eclipse-temurin), Amazon Corretto, IBM Semeru Runtime (OpenJ9), Azul Zulu, and Liberica JDK. AdoptOpenJDK is community‑driven; Corretto and Semeru are cloud‑oriented.
JVM Selection
HotSpot is the default JVM with balanced performance. OpenJ9 (from IBM) offers faster startup and lower memory usage, suitable for containers. If unfamiliar, use HotSpot; for tuning, consider OpenJ9.
Signal Propagation
When a container stops, the termination signal must reach the JVM for graceful shutdown. Using a plain CMD ["java","-jar","app.jar"] or an exec in the entrypoint ensures signal forwarding. Bash scripts or tools like tini and dumb‑init may block signal propagation.
Correct Dockerfiles
Direct run: CMD ["java","-jar","app.jar"] Exec in script: exec java -jar app.jar Bash‑c for simple commands, but test for reliability.
Memory Limits
JVM memory auto‑tuning depends on JDK version and cgroup version. JDK 8u131 supports -XX:+UseCGroupMemoryLimitForHeap; JDK 8u191 adds -XX:+UseContainerSupport. From JDK 11 onward, -XX:+UseContainerSupport is enabled by default, but full support for cgroups v2 starts with JDK 11.0.16 and JDK 17.
DNS Cache
JVM DNS cache defaults to 30 seconds; with a Security Manager it becomes “forever”. Set -Dsun.net.inetaddr.ttl=xxx to control TTL. Tools like Alibaba’s DCM can help debug DNS caching.
Native Compilation
GraalVM can compile Java to native binaries for faster startup, but requires code adjustments and is currently more suitable for new projects. Build with mvn clean package -Pnative after setting JAVA_HOME to GraalVM.
References
eclipse‑temurin Docker images
ibm‑semeru‑runtimes
GitHub project for graceful shutdown example
StackExchange discussion on bash -c JDK‑8230305 bug for cgroups v2 support
Alibaba DCM tool
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
