Layer Cache Mechanics
Layer Cache Mechanics
A layer is reused when its parent layer, instruction text, build args, and file contents are unchanged. That gives the ordering rule — put infrequently changing work first:
FROM node:20-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci # cached until the lockfile changes
COPY src ./src # invalidated on every source commit
RUN npm run build
Everything after a changed COPY re-runs, so a single misplaced COPY . . above npm ci defeats the whole cache. Inspect reality with docker build --progress=plain and look for CACHED on each step.
BuildKit Cache Mounts
BuildKit Cache Mounts
Cache mounts survive even when the layer itself is invalidated, because the cache lives outside the layer graph:
RUN --mount=type=cache,target=/root/.npm npm ci
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
apt-get update && apt-get install -y --no-install-recommends git
The npm cache and apt lists persist across commits and branches. sharing=locked makes concurrent builders take turns on a mount that cannot tolerate parallel writers; use the default shared for read-heavy caches. Bind mounts (type=bind,from=) instead inject build-time context without committing it to a layer.
External Caches and Pitfalls
External Caches and Pitfalls
To reuse cache across machines, export it:
docker buildx build \
--cache-to type=registry,ref=registry.example.com/app:buildcache,mode=max \
--cache-from type=registry,ref=registry.example.com/app:buildcache .
mode=max exports intermediate stages; without it only final layers ship. Inline cache (--build-arg BUILDKIT_INLINE_CACHE=1) embeds cache metadata in the pushed image itself, which only helps for single-stage or final-stage reuse.
Pitfalls. Registries expire old manifests, so cold caches return silently; secrets must never ride in cached layers (--mount=type=secret); and a polluted builder disk is fixed with docker builder prune, not by deleting your Dockerfile.
Quiz
1. What exactly invalidates a cached RUN layer?
2. What does --mount=type=cache give you that ordinary layer caching does not?
3. Why use sharing=locked on an apt cache mount?
Flashcards
Question
Layer cache key
Click to reveal answer
Answer
Parent layer + instruction + args + touched file contents; all equal → CACHED.
Question
Cache mount
Click to reveal answer
Answer
RUN --mount=type=cache,target=... — directory persists outside the layer graph.
Question
sharing=locked
Click to reveal answer
Answer
Serializes concurrent access to a cache mount apt-style tools cannot share safely.
Question
Registry cache
Click to reveal answer
Answer
--cache-to/--cache-from type=registry,ref=... sharing BuildKit cache across machines.
Question
docker builder prune
Click to reveal answer
Answer
Removes dangling builder cache to reclaim disk without touching images in use.
Revision Notes
Key Takeaways
- 1. Cache keys are content-derived — order instructions by change frequency
- 2. Cache mounts keep package-manager state across invalidations
- 3. Export mode=max to registries for CI, and prune rather than delete caches blindly
Interview Tips
- • Predict which steps re-run for a given diff before running the build
- • Explain why a cache mount still helps after COPY src invalidates the layer
Cheat Sheet
Cache key = parent+instruction+args+files; package copy before source; RUN --mount=type=cache (sharing=locked for apt); registry cache mode=max; builder prune.