DevOps & Infrastructure

Docker Image Optimizer

Shrink and harden a Dockerfile -- layer caching, multi-stage builds, and running as non-root -- checked against what the image actually needs at runtime.

When to use this

  • A Dockerfile produces a bloated image or slow builds.
  • Reviewing a new Dockerfile before it's used in production, for size and security basics.
  • Not for application-level performance inside the container -- scope to the image build itself.

The skill file

Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.

SKILL.md
---
name: docker-optimizer
description: Review or optimize a Dockerfile for image size (layer caching, multi-stage builds), build speed, and baseline security (non-root user, minimal base image, no leaked secrets). Use when reviewing a Dockerfile or when image size/build time is a problem.
---

# Docker Image Optimizer

## Size and build speed

- **Layer ordering**: are rarely-changing steps (installing system
  packages, dependency install) before frequently-changing steps (copying
  application source)? Wrong order busts the build cache on every code
  change.
- **Multi-stage builds**: is a build-only toolchain (compilers, dev
  dependencies) being shipped in the final image when it could be
  discarded after a build stage?
- **Base image choice**: is the base image the smallest one that actually
  meets the runtime's needs (slim/alpine variant where compatible), or an
  unnecessarily large default?
- **`.dockerignore`**: does it exclude `.git`, local env files, node_modules/
  build artifacts that shouldn't be copied into the build context?
- **Combined RUN layers**: are related commands (e.g. `apt-get update &&
  apt-get install` in one layer) combined to avoid leaving stale package
  lists in an intermediate layer?

## Security basics

- **Non-root user**: does the final image run as a non-root user, or
  default to root?
- **No secrets baked in**: are build-time secrets (private registry
  tokens, API keys) passed via build secrets/args designed for that
  purpose, not `COPY`'d or `ENV`'d into a layer where they'd persist in
  the image history even if later deleted?
- **Pinned versions**: is the base image tag pinned (not `latest`), and
  are installed package versions pinned where reproducibility matters?

## Output

Findings grouped as size / build-speed / security, each with the specific
Dockerfile line and the fix.

Installing it elsewhere

The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:

Claude Code
.claude/skills/docker-optimizer/SKILL.md

Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /docker-optimizer.

Cursor
.cursor/rules/docker-optimizer.mdc

Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.

Codex CLI / Copilot
AGENTS.md

Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.

Windsurf
.windsurfrules

Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.

Where this goes wrong
  • Recommending a multi-stage build without checking the final stage actually excludes the build-only tooling.
  • Missing a secret baked into an early layer that persists in image history even though a later layer deletes the file.
  • Suggesting alpine as a drop-in base image swap without checking for musl-libc compatibility issues with the actual runtime.