Files
spring-boot-demo/docker-images/docs/08-distroless-in-practice.md
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

21 lines
1.3 KiB
Markdown

# 8. Living with distroless
[← 7. PID 1 and signals](07-pid1-and-signals.md) · [Index](../README.md)
`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](https://ankurm.com/spring-boot-4-kubernetes-probes-graceful-shutdown-cpu-limits-hpa/)
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.