Why your Docker build takes four minutes every time
Layer caching is ordering-sensitive, and most Dockerfiles get the order wrong
- 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.