Hasty Briefsbeta

Bilingual

The physics of Docker build caching

5 hours ago
  • Docker build caching involves three distinct caches: layer cache, mount cache, and image store, each with different lifetimes and invalidation rules.
  • Layer caching is all-or-nothing within a stage; a change invalidates its layer and all subsequent layers in the chain.
  • Mount caches (e.g., package manager caches) persist across builds and make re-runs faster by preserving state, but they are not exported with layer cache backends.
  • Export backends (e.g., GHA, registry) help skip unchanged layers on fresh runners but can be slower than no cache if mount caches are critical, due to import/export overhead.
  • Persistent state (keeping caches between jobs) significantly outperforms export backends in common scenarios like source changes and dependency updates.
  • Layer ordering in Dockerfiles is crucial: place expensive and stable steps before frequently changing content to optimize caching.
  • For compiled languages, mount cache survival is key; export backends cannot replicate this, making persistent builder state essential.
  • Share caches based on image lineage (sets of builds that reuse layers), not just repo boundaries, for optimal efficiency.
  • Caches grow with distinct dependency versions, not build count; some toolchains self-trim, others require manual key resets.
  • Image store caching (e.g., shared /var/lib/docker) reduces pull times for common images, especially beneficial in fan-out patterns.
  • Reproducible builds and tags are important to avoid defeating deduplication in shared image caches.
  • The seven rules of thumb summarize key insights for optimizing Docker caching in CI, balancing layer ordering, mount caches, and distribution.