Cache Mounts

Parallel Build Graphs and Cache Mounts

Independent stages run at the same time: two stages that each print the time and sleep five seconds logged right starts 10:36:34 and left starts 10:36:34 on this host. docker buildx bake (buildx bake) extends this to several targets at once.

A cache mount, RUN --mount=type=cache,target=/root/.npm, gives a step a directory that persists between builds but never becomes part of a layer, so npm 2,036 keeps its downloads even when a changed lockfile reruns npm ci. Prove it by reinstalling BookNest's dependencies with the network switched off:

offline.Dockerfile: installing from the cache mount aloneDockerfile
# syntax=docker/dockerfile:1
FROM node:24-slim
WORKDIR /app
COPY package.json package-lock.json ./
# A new RUN_ID forces this step to run: --no-cache would also empty the cache mount.
ARG RUN_ID
RUN --network=none --mount=type=cache,target=/root/.npm \
    du -sh /root/.npm/_cacache && npm ci --omit=dev --offline --no-audit --no-fund
npm ci with no network, served from the cache mountShell
docker build --progress=plain --build-arg RUN_ID=$RANDOM -f ../offline.Dockerfile \
  -t l3-offline . 2>&1 | grep -E '^#[0-9]+ [0-9.]+ .*[a-z]'
Output
#10 0.118 2.5M  /root/.npm/_cacache
#10 1.165 added 82 packages in 939ms

Cache mounts are keyed by id, which defaults to the target path, so Dockerfiles mounting /root/.npm share one cache (sharing=locked serializes writers). Measured here: --no-cache and --no-cache-filter start cache mounts empty too, and BookNest's 82 small packages installed in about 2 seconds with or without the cache; large trees and slow links gain far more.