Lesson 16 of 30
Ordinary layer caching only gets you so far — BuildKit is the modern build engine underneath `docker build`, and its cache mounts solve the specific case ordinary layers can't: a dependency cache that survives across builds without ever being baked into the image.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
Does the final built image contain what was stored in a `--mount=type=cache` directory?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
BuildKit is the build engine that actually executes docker build on any current Docker installation — it replaced the older, simpler builder, and it's been the default for long enough that most developers use it without ever naming it. Two of its capabilities go meaningfully beyond ordinary layer caching (covered earlier in this track), and both solve real, common problems layer caching alone can't:
RUN --mount=type=cache,target=/path) give a RUN instruction a persistent directory that survives across separate builds, without that directory ever becoming part of any image layer. A package manager's download cache is the canonical use case: normally, pnpm install inside a layer either gets fully cached (nothing changed) or fully re-downloads (anything changed) — there's no middle ground. A cache mount gives it a middle ground: even when the lockfile changes and the install has to actually run, it reuses previously-downloaded packages instead of re-fetching everything from the network.RUN --mount=type=secret,id=...), covered in this track's config-and-secrets lesson, are BuildKit's other headline feature — a value available only to one RUN instruction, never written to any layer.Both are the same underlying idea applied to two different problems: BuildKit can give a RUN instruction access to something (cached files, a secret) without that something becoming part of the image's permanent layer history.
First build: the cache mount is empty, so pnpm install downloads every package from the network.
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
Without the cache mount, editing the lockfile invalidates the install layer completely, and pnpm install re-downloads every dependency from the network on the next build — exactly the ordinary layer-caching behavior from earlier in this track. With --mount=type=cache, the contents downloaded into that mount persist independently of the layer cache: even on a full re-run of pnpm install, most packages are already sitting in the mounted cache directory, and only genuinely new or changed dependencies hit the network. The mount's contents are never part of the final image at all — they exist only for BuildKit's own reuse across builds, on the machine actually running the build.
docker history on the final image shows no trace of what a cache mount held — it's a build-time-only mechanism, entirely separate from what ends up shipped.target path and an optional id, not by the Dockerfile instruction's hash. This is exactly why they survive across builds that would otherwise fully invalidate a normal layer — the cache mount doesn't participate in the layer-cache-key mechanism at all, it's a parallel system.# syntax=docker/dockerfile:1 directive at the top of the Dockerfile is what opts into the newer Dockerfile frontend that understands --mount; omitting it (on an older or misconfigured setup) can silently fail to parse the mount syntax."Our Docker builds are still slow even though we fixed the layer ordering" is a natural follow-up once a candidate has already answered the layer-caching question well, and cache mounts are the correct next-level answer — they solve exactly the case where a dependency install has to rerun (because the lockfile did change) but shouldn't have to re-download everything from scratch. Naming BuildKit as the engine and cache mounts as the specific mechanism is what distinguishes a candidate with hands-on build-performance experience from one who's only optimized instruction ordering.