Incrm logo
INCRM
Angular
Your trial is expiring soon!
You have 3 days left in your trial. Upgrade to pro to continue using all features.
Check out BuilderKit; the next generation of toolkit for building beautiful Angular applications. Use promo code FUSE on checkout for 20% off your purchase!
Dockerfile build cache is thrashing
Every CI build reinstalls all node modules even when only source files changed. What am I doing wrong?
Almost certainly you are copying the whole working tree before installing. That makes the install layer depend on every file in the repo, so any source edit invalidates it.
Copy only the manifest and lockfile first, install, then copy the rest.
dockerfile
FROM node:22-alpine
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build
With that ordering a source-only change reuses the install layer and the build drops to whatever your bundler costs. If CI still misses the cache, the runner is probably starting from an empty layer store, and you need to enable a registry-backed cache explicitly.
bash
docker buildx build \
  --cache-from type=registry,ref=ghcr.io/acme/app:cache \
  --cache-to type=registry,ref=ghcr.io/acme/app:cache,mode=max \
  -t ghcr.io/acme/app:latest .
What does mode=max buy me over the default?
The default only exports the layers of the final image. mode=max also exports intermediate layers, which is exactly what you need for a multi-stage build where the expensive work happens in a stage that gets discarded.
The trade-off is cache size and push time. On a small image it is free, on a large monorepo image it can add a minute to every build, so measure before you keep it.
AI can make mistakes. Check important info.