Course outline

Docker / Build evidence and production operations / Lesson 14

Cache design and measured build performance

Reuse valid work while preserving correct dependency invalidation and trust boundaries.

About 4 min readContent reviewed
On this page

Lesson goals

  • Explain instruction-cache invalidation and cache mounts.
  • Measure cold and warm builds without treating caches as authoritative artifacts.

Cache validity follows input dependencies

A cached instruction can be reused when its relevant inputs and preceding state match the builder's cache rules. Changing an early copied source can invalidate later work even if the instruction text is unchanged. Arrange stable dependency descriptions before frequently changing application files where that preserves semantics. Cache is an optimization: a correct build must remain possible from the declared source and dependencies when reusable cache entries are unavailable.

Separate module metadata from source changes

The earlier Go fixture has no third-party requirements, but its structure illustrates a useful boundary. Copy module metadata before source, resolve declared modules, then compile after copying source. In a project that has go.sum, copy and review that lock evidence alongside go.mod. Do not generate dependencies from an unreviewed network lookup simply to make the cache hit; correct dependency identity matters more than preserving an attractive build duration.

dockerfile A source-aware compiler cache boundary
# syntax=docker/dockerfile:1
FROM golang:1.26-alpine AS build
WORKDIR /src
COPY go.mod ./
RUN go mod download
COPY main.go ./
RUN --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 go build -trimpath -o /out/parcel ./
FROM scratch
COPY --from=build /out/parcel /parcel
USER 65532:65532
ENTRYPOINT ["/parcel"]

The complete recipe uses the previously declared go.mod and main.go. Changing only main.go leaves the earlier module-resolution input unchanged. The cache mount accelerates reusable compiler work without being copied into the final image. Because the fixture has no external modules, no dependency-download speedup is claimed.

Cache mounts are disposable working state

A BuildKit cache mount persists selected working directories across builds under builder management. Tools must tolerate its absence and any supported concurrent use. Cache contents can be stale or influenced by other builds sharing the same trust domain, so do not store release-only truth or secrets there. Choose cache ids and sharing behavior according to the package tool and tenancy model rather than letting unrelated untrusted builds share writable working state by accident.

Inspect usage and progress without inventing timings

Build logs can distinguish cached steps, executed commands, context transfer, and artifact export. Compare cold and warm conditions using the same source, platform, builder, and network assumptions. Registry transfer can dominate a build whose compilation is already cached. Inspect cache consumption before discussing retention, but do not run broad pruning as a performance experiment on a shared builder; cache ownership and rollback evidence may belong to other projects.

bash Inspect selected builders and cache usage
docker buildx ls
docker buildx du

These diagnostic views depend on an authorized existing builder and may query its endpoint. They do not rebuild or prove any speedup, and no sizes are fabricated. Identify the selected builder and ownership before interpreting cache totals; a remote builder can have a different cache from the local engine.

Invalidate for correctness, not appearance

A network package repository can change even when a RUN command string does not. Pin dependencies and deliberately refresh approved inputs rather than assuming cache reuse proves freshness. Secret values are not automatically cache keys; use a separate nonsecret revision when a changed credential legitimately changes the expected artifact. External cache import/export needs access controls because it can reveal intermediate content and metadata. Document trusted producers and retention rather than treating every cache endpoint as interchangeable.

Common errors and fixes

A source edit rebuilds every dependency step.

Why it happens
A broad COPY occurred before stable dependency resolution.
How to fix it
Separate reviewed dependency metadata from frequently changing source where valid.
Prevent it next time
Review the input graph rather than adding cache flags blindly.

A build succeeds only when an old cache exists.

Why it happens
Required inputs or generated artifacts were not declared in the build contract.
How to fix it
Restore complete source and dependency declarations and test a clean build separately.
Prevent it next time
Treat cache loss as a supported operational condition.

An apparently cached build uses stale dependency content.

Why it happens
Mutable network inputs were assumed to participate in instruction invalidation automatically.
How to fix it
Pin and refresh dependency revisions through a reviewed update process.
Prevent it next time
Separate freshness policy from cache-hit rate metrics.

Check your understanding

1. Will editing main.go necessarily rerun go mod download in the example?

Show worked solution

Not when the earlier module metadata and relevant prior inputs remain unchanged and a valid cache entry is available. The copy of main.go occurs later. This is a possible reuse boundary, not a guaranteed timing claim; missing cache or changed base and builder inputs can still require execution.

2. Why is warm-versus-cold comparison insufficient without recording platform and builder?

Show worked solution

Different architectures, remote cache locations, emulation, network paths, and export behavior can change the cost. Hold relevant inputs constant or explicitly report differences. Otherwise a claimed cache improvement may actually measure another machine, a previously pulled base, or a changed artifact-output path.

Key takeaways

  • Caches reuse valid work; they must not become undeclared source dependencies.
  • Measure build phases and preserve cache trust and ownership boundaries.

Official references