Files
spring-boot-demo/docker-images/docs/08-distroless-in-practice.md
T
asmhatreandClaude Opus 5 644da9e65e Add docker-images: one Spring Boot 4 service packaged nine ways
Companion code for "Dockerizing Spring Boot 4: Layered Jars, Buildpacks,
Distroless and Image Size Benchmarks". Fat jar on JDK and JRE, layered jar
on Debian, Alpine and distroless, jlink, the JDK 25 AOT cache, Paketo
buildpacks and Jib, each measured for size on disk and pushed, rebuild
delta, startup, user and shell. Also PID 1 and signal handling, the jdeps
module gap, AOT cache mismatches and buildpacks memory calculation.
Transcripts in docs/output/, regenerated by scripts/run-all.sh.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C3TETMrqVUWeFkNtz3Jbo3
2026-09-11 17:11:46 +00:00

1.3 KiB

8. Living with distroless

← 7. PID 1 and signals · Index

gcr.io/distroless/java25-debian13:nonroot gives you: a JRE, glibc, CA certificates, time zone data, and 25 OS packages in total - against 106 in eclipse-temurin:25-jre. No shell, no package manager, uid 65532. It is the variant recommended in the article, and it changes a few habits.

  • RUN is impossible in the final stage. Do everything - extraction, jlink, training runs - in a builder stage with a shell, then COPY.
  • ENTRYPOINT must be exec form.
  • docker exec -it ... sh does not work. On Kubernetes use an ephemeral debug container that shares the process namespace: kubectl debug -it <pod> --image=busybox:1.37 --target=app. With Docker: docker run -it --pid=container:<name> --network=container:<name> busybox.
  • A preStop hook of exec: ["sh", "-c", "sleep 10"] fails, because there is no sh. Use the native sleep action (on by default since Kubernetes 1.30, stable in 1.34). The Kubernetes article measures what that failure costs during a rolling update.
  • Tags are the variant. :latest runs as root, :nonroot as 65532, :debug adds a BusyBox shell - useful for a one-off investigation, never for production.