Skip to Content

Layers & Build Cache

When to use

You want fast Docker builds; layer order affects cache hit rates.

Analogy

layers are checkpoints in a video game - if you didn’t change something, you skip past that checkpoint. Re-run a missed layer and all layers after rerun too.

Data-flow diagram

  FROM ubuntu:22.04    -> A (digest of ubuntu:22.04)
  RUN apt-get install...-> B (command + parent A)
  COPY requirements.txt -> C (file content hash)
  RUN pip install...    -> D (parent C)
  COPY . .              -> E (entire source tree hash)
  change ONE file in COPY . . -> E misses; D/C still cached

Deep explanation

Docker’s build cache works layer by layer: each layer’s cache key is the instruction body + digest of parent layer + contents of any referenced files. If even one byte changes, the layer AND every later layer is rebuilt. Optimising Dockerfile = ordering instructions least-changed-first. BuildKit (default since Docker 23.0) extends this with parallel builds and content-addressable cache.

Examples

Example 1

# BAD
COPY . .
RUN pip install -r requirements.txt
# GOOD
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

in the GOOD order, source code edits don’t bust the pip install layer cache.

Example 2

DOCKER_BUILDKIT=1 docker build -t myapp .

BuildKit enables content-addressed cache, parallel execution, —mount=type=cache.

Example 3

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

BuildKit cache mount persists pip cache across builds even when a layer is rebuilt.

Common mistake

Having RUN echo $(date) that changes every build, busting cache. Copying a build dir .git or node_modules that invalidates cache for irrelevant reasons.

Key takeaway

Order instructions least-changed-first; use .dockerignore; enable BuildKit for advanced caching; remember cache is local to each builder by default.

Production Failure Playbook

Failure scenario 1: build-context-5gb

Failure scenario 2: cache-busted-by-env-var