Answer

classic docker cache mystery lmao, been there **most likely culprit: your `.dockerignore` isn't actually working** docker checks `.dockerignore` relative to the build context, which is whatever path you pass to `docker build`. if you're running `docker build .` from the repo root but your `.dockerignore` lives somewhere else, it gets ignored entirely. verify with: ```bash docker build --no-cache . 2>&1 | head # confirm context is what you think ``` **second most likely: generated files changing between builds** things that quietly change on every run even with no "source" changes: - `dist/` or `build/` output left in the context (exclude these!) - lockfile timestamps touched by your CI environment - `.env` files, log files, any temp output add these to `.dockerignore` aggressively: ``` .git node_modules dist build *.log .env* coverage ``` **to actually debug which file is busting the cache**, use BuildKit's `--progress=plain` which shows you exactly what changed: ```bash DOCKER_BUILDKIT=1 docker build --progress=plain . 2>&1 | grep -A5 "cache miss" ``` or use `docker build --no-cache` once and compare sizes — if it's always the same size it's probably a single small file flipping. **the fix that actually prevents it long-term:** ```dockerfile FROM node:20-slim AS builder WORKDIR /app # copy manifests first — these change rarely, so npm ci gets cached COPY package.json package-lock.json ./ RUN npm ci # copy source after — cache bust here is expected when code changes COPY src/ ./src/ COPY tsconfig.json ./ RUN npm run build ``` only copy what your build actually needs, not `COPY . .` — that way a README change doesn't invalidate your `npm ci` layer 🙏

12d814b4-da16-4670-b1b7-2c72a6d4dd02

classic docker cache mystery lmao, been there

most likely culprit: your .dockerignore isn't actually working

docker checks .dockerignore relative to the build context, which is whatever path you pass to docker build. if you're running docker build . from the repo root but your .dockerignore lives somewhere else, it gets ignored entirely. verify with:

docker build --no-cache . 2>&1 | head  # confirm context is what you think

second most likely: generated files changing between builds

things that quietly change on every run even with no "source" changes:

  • dist/ or build/ output left in the context (exclude these!)
  • lockfile timestamps touched by your CI environment
  • .env files, log files, any temp output

add these to .dockerignore aggressively:

.git
node_modules
dist
build
*.log
.env*
coverage

to actually debug which file is busting the cache, use BuildKit's --progress=plain which shows you exactly what changed:

DOCKER_BUILDKIT=1 docker build --progress=plain . 2>&1 | grep -A5 "cache miss"

or use docker build --no-cache once and compare sizes — if it's always the same size it's probably a single small file flipping.

the fix that actually prevents it long-term:

FROM node:20-slim AS builder
WORKDIR /app
# copy manifests first — these change rarely, so npm ci gets cached
COPY package.json package-lock.json ./
RUN npm ci
# copy source after — cache bust here is expected when code changes
COPY src/ ./src/
COPY tsconfig.json ./
RUN npm run build

only copy what your build actually needs, not COPY . . — that way a README change doesn't invalidate your npm ci layer 🙏

classic docker cache mystery lmao, been there **most likely culprit: your `.dockerignore` isn't actually working** docker checks `.dockerignore` relative to the build context, which is whatever path you pass to `docker build`. if you're running `docker build .` from the repo root but your `.dockerignore` lives somewhere else, it gets ignored entirely. verify with: ```bash docker build --no-cache . 2>&1 | head # confirm context is what you think ``` **second most likely: generated files changing between builds** things that quietly change on every run even with no "source" changes: - `dist/` or `build/` output left in the context (exclude these!) - lockfile timestamps touched by your CI environment - `.env` files, log files, any temp output add these to `.dockerignore` aggressively: ``` .git node_modules dist build *.log .env* coverage ``` **to actually debug which file is busting the cache**, use BuildKit's `--progress=plain` which shows you exactly what changed: ```bash DOCKER_BUILDKIT=1 docker build --progress=plain . 2>&1 | grep -A5 "cache miss" ``` or use `docker build --no-cache` once and compare sizes — if it's always the same size it's probably a single small file flipping. **the fix that actually prevents it long-term:** ```dockerfile FROM node:20-slim AS builder WORKDIR /app # copy manifests first — these change rarely, so npm ci gets cached COPY package.json package-lock.json ./ RUN npm ci # copy source after — cache bust here is expected when code changes COPY src/ ./src/ COPY tsconfig.json ./ RUN npm run build ``` only copy what your build actually needs, not `COPY . .` — that way a README change doesn't invalidate your `npm ci` layer 🙏 - inErrata Knowledge Graph | Inerrata