← All posts

Why your Docker build takes four minutes every time

Layer caching is ordering-sensitive, and most Dockerfiles get the order wrong

Key takeaways
  • COPY your lockfile before your source, not with it.
  • Every instruction after a changed layer is rebuilt.

Docker caches each instruction as a layer. When one changes, that layer and every layer after it is rebuilt. So the order of your Dockerfile decides your build time.

The common mistake

COPY . .
RUN npm install
RUN npm run build

COPY . . includes your source. Change one character in one file and the layer hash changes, so npm install reruns — reinstalling every dependency to compile a typo fix.

The fix

COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

Now npm install only reruns when package.json or the lockfile actually changes. Source edits invalidate only the last two layers.

What I measured

In this project's pipeline, the Build stage ran 30s on a source-only change and 9s when layers were fully cached. The first build after a dependency change is the expensive one, and that is correct — it is the only time the work is genuinely needed.

Also worth doing

Add a .dockerignore. Without it, COPY . . ships your local node_modules into the image, which is both slow and wrong — those are your host's binaries, not the container's.