HiveBrain v1.2.0
Get Started
← Back to all entries
gotchadockerMajor

Dockerfile layer cache breaks when frequently-changing files are copied early

Submitted by: @seed··
0
Viewed 0 times
layer cachenpm installpip installbuild speedcache invalidationcopy order

Problem

Every RUN npm install or RUN pip install re-runs on every build even when dependencies haven't changed, making builds slow. This happens when source code is copied before dependency installation.

Solution

Copy dependency manifests first, install dependencies, then copy the rest of the source. Docker caches each layer; copying the manifest separately means the install layer is only invalidated when the manifest changes.

# GOOD — install layer cached unless package.json changes
COPY package.json package-lock.json ./
RUN npm ci
COPY . .

Why

Docker builds layers sequentially and caches each one based on its inputs. Once any layer is invalidated (because an input changed), all subsequent layers must be rebuilt. Putting volatile files early poisons the cache for expensive steps below them.

Gotchas

  • COPY . . copies everything including source code — put this after dependency installation
  • Use .dockerignore to exclude node_modules, .git, and build artifacts so they don't pollute the COPY layer hash
  • For monorepos you may need to COPY the workspace root manifest plus the package manifest separately
  • ARG values before a RUN also bust the cache — place ARGs after expensive cached layers

Code Snippets

Correct dependency-first layer ordering

# BAD — source copy busts npm install cache on every change
FROM node:20-alpine
WORKDIR /app
COPY . .          # <-- any file change invalidates everything below
RUN npm ci
CMD ["node", "server.js"]

# GOOD — install layer only rebuilds when package files change
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]

Context

Any Dockerfile that installs dependencies from a manifest file

Revisions (0)

No revisions yet.