Understanding Docker Build Cache
Docker build cache makes image builds fast by reusing layers. Understanding how it works helps you write efficient Dockerfiles.
How Build Cache Works
Docker builds images layer by layer. If a layer hasn't changed, Docker reuses the cached version instead of rebuilding it.
Cache Hit
Docker compares the instruction and its inputs:
Cache Miss
When any instruction changes, that layer AND all subsequent layers are rebuilt.
The Cache Invalidation Chain
This is the key insight:
FROM node:20-alpine # Cached
COPY package.json . # Cached (if file unchanged)
RUN npm install # Cached (depends on previous layer)
COPY . . # MISS (source code changed)
RUN npm run build # MISS (because previous layer changed)
Once COPY . . invalidates, everything after it rebuilds.
Optimization Strategies
1. Order by Change Frequency
Put rarely-changing layers first, frequently-changing layers last.
Good:
COPY package.json .
RUN npm install
COPY . .
Bad:
COPY . .
RUN npm install
In the bad version, every source code change invalidates the npm install cache.
2. Separate Dependencies from Code
Install dependencies before copying source code. Dependencies change less frequently than source code.
3. Use .dockerignore
Exclude node_modules, .git, tests, and docs. Smaller build context = faster builds and fewer cache invalidations.
4. Minimize RUN Layers
Each RUN creates a layer. Combine related commands:
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
5. Use BuildKit
DOCKER_BUILDKIT=1 enables improved caching, parallel builds, and cache mounts.
Cache Mounts
BuildKit cache mounts persist across builds:
RUN --mount=type=cache,target=/root/.npm npm install
npm's cache directory persists between builds. Dramatically faster repeated installs.
These optimizations make your TinyPod deployments faster — smaller images build and pull quicker.