How does the Docker build cache work, and how do you write Dockerfiles that stay fast?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Each Dockerfile instruction is a layer; Docker reuses cached layers when the instruction and its inputs are unchanged, and invalidates that layer plus everything after it on any change. Keep it fast: COPY dependency manifests first, RUN install, then COPY source — so code edits reuse the install layer. Exclude junk with .dockerignore.
Detailed explanation
The docs demo makes this visceral: first docker build . takes ~20s (yarn install ~10s), an unchanged rebuild takes ~1s with every step CACHED. Three invalidation rules: a changed RUN command busts its layer; any changed file under COPY/ADD (content or permissions) busts that layer; once one layer busts, all following layers bust to stay consistent. The classic mistake is COPY . . before RUN yarn install — every source edit reinstalls identical dependencies. Fix: COPY package.json yarn.lock ./ → RUN yarn install --production → COPY . ., plus a .dockerignore containing node_modules so local build artifacts never enter the context (context shrank from MBs to KBs in the demo). After the reorder, editing src/static/index.html rebuilds in ~1.2s with the install step CACHED. Faster builds also mean faster pushes/pulls since unchanged layers are shared.
Official docs:Docker docs: Using the build cache
Example
# ❌ slow: any source change reinstalls deps
FROM node:22-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
# ✅ fast: dep layer survives source edits
FROM node:22-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
EXPOSE 3000
CMD ["node", "src/index.js"]
# .dockerignore
node_modulesInterview tip
Quote the 20s→1s numbers, state the cascade rule ('one bust poisons everything below'), then show the deps-first reorder — that sequence is the whole answer.
Common mistakes
- COPYing the entire context before installing dependencies.
- Omitting .dockerignore so node_modules and git history bloat the context.