Docker dive optimization
Analyze a Docker image's actual byte breakdown with dive, auto-fix mechanical waste (unmerged cache-purge layers, missing no-cache flags), propose heavy-tool-for-narrow-need swaps for joint review, and file TODOs for the rest
Load the docker-image-slimming skill first β it defines how to fetch dive without touching the
system, how to run it non-interactively (-j/--json, no TUI), the verified JSON schema, and the
three-bucket classification (auto-fix / propose / TODO) this command drives. Don't duplicate that
reasoning here β this file only adds project discovery, the build step, and the reporting/TODO
wiring.
1. Discover the target(s)β
With $ARGUMENTS:
- If it looks like an image tag (contains
:or resolves viadocker image inspect), analyze that tag directly without building. - If it's a file path, use it directly.
- Otherwise treat it as a glob and search for matching Dockerfile-shaped filenames.
Without $ARGUMENTS (auto-discovery):
- Look for a
docker-compose.ymlorcompose.yamlat the project root. If found, list the services and theirbuild:contexts to identify the main application image. - If no compose file, look for a
Dockerfileat the project root. - Skip Dockerfiles that live under example, sample, tutorial, or documentation directories
(e.g.,
examples/,docs/,blog/,.unpublished/,samples/) unless explicitly passed as an argument β these are illustration files, not images to optimize. - If multiple candidates remain after filtering, list them and ask the user to pick one.
State which target was selected before moving on.
2. Build the imageβ
If a compose file was found: use the compose command to build the target service:
docker compose build <service-name>
Otherwise, fall back to a direct build:
docker build -q -f <Dockerfile> -t dive-optimize/<basename>:local <context-dir>
State which command was used and the resulting image tag before running dive.
3. Run dive, classifyβ
Per the skill: fetch/verify the dive binary into the scratch directory if not already on PATH,
run dive <tag> -j <scratch>/dive-<basename>.json, then classify every finding into Bucket
A/B/C. Report, before doing anything else: current image.sizeBytes and image.efficiencyScore, and
the count of findings per bucket.
4. Bucket A β apply nowβ
Apply every Bucket A finding with Edit, same as any other file edit in this conversation β gated by
the normal tool-approval prompt. List each merge/flag added with its file:line.
Then rebuild and re-run dive to confirm the fix actually worked (the skill's "verify the fix"
step) β report image.sizeBytes and image.efficiencyScore before vs. after. If a Bucket A edit
didn't measurably help, say so plainly rather than reporting success on the edit alone.
5. Bucket B β propose, waitβ
Present every Bucket B finding as a numbered list: dive's evidence (layer size, % of image,
command), what it appears to be there for, and a concrete alternative with its own trade-off (a
standalone binary instead of a full runtime, a discarded builder stage, a slimmer base image). Stop
here and wait for a decision on each item β do not touch the Dockerfile for any of these without an
explicit go-ahead, even for the ones that look obviously right. If the user greenlights one, apply it
with Edit, then rebuild + re-run dive the same way as step 4 to confirm the win.
6. Bucket C β Document remaining findingsβ
List every remaining finding as a numbered item: the layer size, the command that caused it, and
a one-line description of why it can't be fixed automatically. Do not touch the Dockerfile for any
of these.
Track them in whatever backlog system the project uses β a GitHub issue, a comment in the Dockerfile itself, a plain text file, or the team's task tracker. The only requirement is that they don't get lost.
In the final report, give the size/efficiency before vs. after from step 4, list the items awaiting a decision from step 5, and list the Bucket C items with enough context for a future session to pick them up without re-running dive.