Quick answer
The Docker Image Optimizer statically analyzes a pasted Dockerfile and reports what's making the image bigger or builds slower — unpinned/bloated base images, cache-busting COPY order, apt/apk caches left in layers, missing multi-stage builds, baked-in secrets — each with the exact fix. It's an advisor, not a builder, and everything runs in your browser: your Dockerfile is never uploaded.
Key takeaways
- Base image is the biggest lever —
node:latestis ~430 MB before your code;-slim/-alpinevariants cut most of it. - Layers are additive — cleanup only shrinks the image when it happens in the same
RUNthat made the mess. - Copy manifests before source —
COPY package*.json ./→ install →COPY . .keeps dependency layers cached across code changes. - Multi-stage builds ship only the output — compile with the full toolchain, run on a slim base.
- 100% private — pure client-side static analysis; nothing you paste leaves your browser.
What does it check?
| Check | Why it matters |
|---|---|
Unpinned / :latest base image | Non-reproducible builds; surprise upstream changes |
Bloated base (full node/python/openjdk…) | Hundreds of MB a -slim/-alpine/JRE variant avoids |
COPY . . before dependency install | Every code change reinstalls all dependencies (cache bust) |
apt-get/apk without same-layer cleanup | Package caches baked permanently into the layer |
| Build step without multi-stage | Compilers and dev deps ship in the production image |
npm install / pip install flags | npm ci --omit=dev, --no-cache-dir — smaller and reproducible |
Secrets in ENV/ARG | Readable by anyone who pulls the image (docker history) |
Missing USER, ADD vs COPY, cd vs WORKDIR, layer count, .dockerignore | Security and maintainability hygiene |
How does it work?
The pasted Dockerfile is parsed into instructions (handling \ line continuations, comments, and multi-stage FROM … AS boundaries), then a set of static rules runs over the instruction list. Rules are stage-aware — a fat golang image in a build stage of a multi-stage file is correct and won't be flagged, while the same image as the final stage will be. Every finding is anchored to the line that caused it and paired with the concrete replacement, and the whole report can be copied or downloaded as text for a PR description or team chat.
Is it private?
Yes. The analysis is plain JavaScript running in your browser tab — the Dockerfile you paste is never uploaded or sent to a server. Dockerfiles routinely reveal internal registry hostnames, service structure, and occasionally real secrets in ENV lines, so a Dockerfile analyzer that uploaded your file would be its own security problem. If a finding shows a baked-in secret, rotate it — and scrub any build logs you share with the Log Redactor.
What it is not
This is a static advisor: it reads text and applies rules. It doesn't build the image, measure real layer sizes, scan for CVEs, or execute anything. Quoted image sizes are typical published sizes for the official images, meant for orientation — your exact numbers depend on version and architecture. For measuring an already-built image layer by layer, pair it with local tools like docker history or dive.
Known limitation: BuildKit heredoc blocks (RUN <<EOF … EOF) aren't parsed — commands inside a heredoc body are skipped rather than analyzed, so an apt-get install inside one won't be checked. No false findings are produced; the block is simply not inspected.
Hitting Docker errors rather than size problems? The error reference covers the common ones: no space left on device (often caused by exactly the image bloat this tool flags), exited with code 137 (OOMKilled), exec format error (wrong-architecture base image), and Cannot connect to the Docker daemon.
Frequently Asked Questions
What does the Docker Image Optimizer do?
Paste a Dockerfile and it statically analyzes the instructions, then reports line-anchored findings with concrete fixes: an unpinned or bloated base image, COPY ordering that breaks layer caching, apt/apk installs without same-layer cleanup, a missing multi-stage build, npm install instead of npm ci, pip without --no-cache-dir, secrets baked into ENV/ARG, running as root, and a .dockerignore reminder. Each finding explains why it costs image size or build time and shows the exact change to make.
Does it build or run my image?
No — it is an advisor, not a builder. It only reads the Dockerfile text you paste and applies static-analysis rules to it. Nothing is built, pulled, or executed, so the advice is based on the instructions themselves, not on measuring a real image. For actual layer-by-layer size measurement of a built image, use a local tool like docker history or dive alongside it.
Is my Dockerfile uploaded anywhere?
No. The analysis is plain JavaScript running in your browser — the Dockerfile you paste is never uploaded or transmitted. Dockerfiles frequently reveal internal registry names, service layout, and sometimes accidentally-committed secrets, so keeping the analysis fully client-side is the point.
Why is my Docker image so large?
The usual causes, in order of impact: a full base image where a -slim or -alpine variant exists (often 300+ MB of difference), no multi-stage build so compilers and dev dependencies ship in the final image, package-manager caches left in layers (apt lists, pip wheels, npm cache), and COPY . . dragging node_modules, .git and build output into the image because there is no .dockerignore. This tool flags each of these from the Dockerfile text.
What is the COPY ordering / layer caching issue?
Docker caches each instruction as a layer and reuses it only if nothing above it changed. If you COPY . . before running npm ci or pip install, then any source-file change invalidates the COPY layer and everything after it — so dependencies reinstall from scratch on every build. The fix is to copy only the dependency manifest first (package*.json, requirements.txt, go.mod), install, and copy the rest of the source afterwards.
Why does deleting files in a later RUN not shrink the image?
Image layers are additive: a file created in one layer is stored in that layer forever, and a later rm only hides it. That is why cleanup must happen inside the same RUN instruction that created the files — apt-get install -y pkg && rm -rf /var/lib/apt/lists/* in one command shrinks the layer, while a separate RUN rm afterwards does not.
When should I use a multi-stage build?
Whenever the image needs tools to build that it does not need to run: compiling TypeScript, bundling a frontend, go build, cargo build, or mvn package. Build in a first stage with the full toolchain, then COPY --from=build only the output into a slim runtime stage. The final image ships without compilers, dev dependencies, or intermediate artifacts — routinely cutting hundreds of megabytes.
Last updated: July 2026