DOCKER CACHE ORDER CHECK · RUNS IN YOUR BROWSER

Is your Dockerfile busting its own build cache?

Paste a Dockerfile and see whether its instruction order defeats Docker's own layer cache: a dependency manifest copied and installed after the whole build context, an install command with no isolated manifest copy at all, and an apt-get update run without install in the same layer — the exact anti-patterns Docker's own "Leverage build cache" documentation names and gives the fix for.

Nothing is uploaded. Everything runs in this browser against the text you paste in.

Check a Dockerfile

Prefer a CLI, or want this in CI before a merge?

Same logic, zero dependencies, one file:

node cli.mjs                       # scan every Dockerfile under .
node cli.mjs /path/to/repo         # scan a specific checkout
node cli.mjs --format json
node cli.mjs --fail-on-risk        # exit 2 if any finding exists

Get cli.mjs — Node 18+, nothing to install, no network call ever. --fail-on-risk makes it a one-line CI gate on any Dockerfile change.

What's checked

CheckHow
Manifest copied/installed after a broad copyA dependency manifest (package.json, requirements.txt, go.mod, Gemfile, composer.json, Cargo.toml, ...) is copied and its install command runs, but only after a whole-build-context COPY . . already ran earlier in the same build stage
Install with no isolated manifest copyAn install command (npm ci, pip install -r requirements.txt, ...) runs with no earlier instruction naming its manifest file specifically — only a broad copy ever reaches it, so there is no dependency layer to cache at all regardless of order
apt update/install split across layersA RUN instruction runs apt-get update (or apt update) without also running install/upgrade/dist-upgrade in that same instruction — Docker's own Dockerfile best practices name this exact split as the cause of a stale, separately-cached package index

Checked ecosystems: npm/yarn/pnpm, pip, Go modules, Bundler, Composer, and Cargo. Each build stage (every section between FROM lines) is checked independently, and COPY --from=<stage> is never treated as a broad context copy, since it copies another stage's output rather than your source tree. See why this happens, and this checker's own named limits, or how this compares to reviewing a Dockerfile by eye.

Common questions

Why does putting COPY . . before installing dependencies break the Docker build cache?

Docker caches each instruction's layer and only re-runs an instruction (and everything after it) when its own inputs change. If COPY . . runs before the dependency install step, that COPY layer's cache key includes every file in your source tree — so any source change at all, even a one-line comment, invalidates it and every layer after it, including the install. Copying just the manifest file (package.json, requirements.txt, go.mod) and running the install before copying the rest of the source means the install layer's cache key only changes when the manifest itself changes.

Why does apt-get update need to be in the same RUN as apt-get install?

Docker's own Dockerfile best practices documentation states this directly: a RUN apt-get update by itself is cached as its own layer, and Docker will reuse that cached layer on a later build even though the actual package index it downloaded is now stale. If a later, separately cached RUN apt-get install then runs against that stale cached update, it can resolve versions the package index no longer serves and fail, or silently install older packages than a fresh update would have found.

What if my Dockerfile never copies a manifest file at all?

Then there is no dependency layer to cache in the first place: the only route by which the manifest reaches the image is a broad copy, so any changed file in the build context invalidates the install regardless of instruction order. This checker reports that case separately ("install with no isolated manifest copy") because the fix is different — add a COPY that names the manifest file specifically, before the broad copy, not just reorder existing instructions.

Is anything uploaded?

No. Everything is computed in your browser from the Dockerfile text you paste in, and nothing you type is sent anywhere. The CLI makes no network call either — it only reads files already on your own disk.