Files
spring-boot-demo/docker-images/docs/03-layered-jars.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

34 lines
1.8 KiB
Markdown

# 3. Layered jars: the win is the second push
[← 2. Measuring size](02-measuring-size.md) · [Index](../README.md) · Next: [4. Buildpacks →](04-buildpacks.md)
`fatjar-jre` and `layered-jre` are the same size: 377 MB on disk, 144 MB pushed. The layers are the
same bytes, cut differently.
What differs is the next build. [`measure-rebuild.sh`](../scripts/measure-rebuild.sh) changes one
string constant, rebuilds every variant, and counts the layer digests that did not exist before
([`rebuild-delta.txt`](output/rebuild-delta.txt)):
```
variant new layers bytes to push image total share
fatjar-jdk 1 of 7 23422K 178M 13.1%
fatjar-jre 1 of 7 23422K 144M 16.2%
layered-jre 1 of 11 6K 144M 0.0%
layered-alpine 1 of 10 6K 98M 0.0%
layered-distroless 1 of 39 6K 97M 0.0%
jlink-distroless 1 of 39 6K 76M 0.0%
aot-cache 2 of 12 15323K 160M 9.6%
buildpacks 2 of 20 64K 125M 0.1%
jib 1 of 10 2K 144M 0.0%
```
A fat jar re-ships all 23 MB of dependencies on every commit; a layered image ships 6 KB. Multiply
by deployments per day and nodes per cluster - every node that already has revision 1 downloads
only the changed layers.
Layers only help if their order matches change frequency. Put your own `COPY` of configuration
files *after* the dependency layers, never before, or every change re-ships everything below it.
Snapshot dependencies get their own layer because they change without a version bump.
Jib and buildpacks layer the same way without being asked.