docker/SKILL.md
Modern Docker workflows - image optimization, debugging, fast builds with dive, lazydocker, and BuildKit
npx skillsauth add snqb/my-skills dockerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Modern Docker tools and workflows. For Dockerfile syntax, see ~/.claude/references/docker-best-practices.md.
# Install essentials
brew install lazydocker dive
# Enable BuildKit
echo 'export DOCKER_BUILDKIT=1' >> ~/.zshrc
source ~/.zshrc
# Interactive mode
dive myimage:latest
# Tab: switch layers/files
# Space: expand directories
# Ctrl+U/D: page up/down
# CI mode (get efficiency score)
dive myimage:latest --ci
Common culprits:
/var/cache/*, /var/lib/apt/lists/*)Target efficiency: 95%+
Remove APT cache:
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/* /var/log/*
Use Alpine (no APT at all):
FROM python:3.12-alpine # 45MB vs 130MB (slim)
RUN apk add --no-cache build-base # Auto-cleans
Multi-stage builds:
FROM node:20 AS builder # 1.1GB (build tools)
RUN npm ci && npm run build
FROM node:20-alpine # 180MB (runtime only)
COPY --from=builder /app/dist ./dist
# Before/after comparison
docker images | grep myimage
# Goal: 2-3x size reduction for typical apps
Real-world targets:
lazydocker
Navigation:
d: remove containers: stop/startr: restartl: view logs/: searchPro tips:
docker logs -f juggling)# syntax=docker/dockerfile:1.4
# npm cache persists between builds
RUN --mount=type=cache,target=/root/.npm \
npm ci
# pip cache
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
# cargo cache
RUN --mount=type=cache,target=/usr/local/cargo/registry \
cargo build --release
Win: 10min → 30sec rebuilds (after first build)
# Old way (leaks in image history) ❌
ARG GITHUB_TOKEN
RUN git clone https://${GITHUB_TOKEN}@github.com/private/repo
# BuildKit way ✅
RUN --mount=type=secret,id=github_token \
git clone https://$(cat /run/secrets/github_token)@github.com/private/repo
# Build with secret
docker build --secret id=github_token,src=$HOME/.github/token -t myapp .
RUN --mount=type=ssh \
pip install git+ssh://[email protected]/private/package.git
# Build with SSH agent
docker build --ssh default -t myapp .
FROM base AS deps
RUN npm ci
FROM base AS test
COPY --from=deps /app/node_modules ./node_modules
RUN npm test
FROM base AS build
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build
# deps, test, build run in parallel!
FROM base AS final
COPY --from=build /app/dist ./dist
Faster builds:
CLI same as Docker:
docker ps # Works exactly the same
docker compose up
Resource usage:
Quirks:
# Verbose build output
DOCKER_BUILDKIT=1 docker build --progress=plain -t myapp .
# No cache (fresh build)
docker build --no-cache -t myapp .
# Check layer-by-layer
dive --source docker://myapp:latest
# DNS not resolving
echo '{"dns": ["8.8.8.8", "8.8.4.4"]}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker # Linux
# OrbStack: Settings → Restart
# Container can't reach internet
docker run --rm alpine ping -c 3 google.com
# Check registry auth
docker login
# Pull with different architecture
docker pull --platform linux/amd64 myimage:latest
# Use mirror if blocked
# Edit /etc/docker/daemon.json:
{
"registry-mirrors": ["https://mirror.gcr.io"]
}
Problem: manifest unknown errors when pulling specific versions.
Always verify tags exist on Docker Hub before pinning:
# Check available tags for an image
curl -s "https://registry.hub.docker.com/v2/repositories/browserless/chrome/tags?page_size=100" \
| jq -r '.results[].name' | grep "puppeteer"
# For official images (different API)
curl -s "https://hub.docker.com/v2/repositories/library/postgres/tags?page_size=50" \
| jq -r '.results[].name'
# For GitHub Container Registry
curl -s "https://ghcr.io/v2/flaresolverr/flaresolverr/tags/list" \
| jq -r '.tags[]'
Common gotchas:
Semantic versioning assumptions:
# ❌ Assumed exists, doesn't
image: browserless/chrome:1-puppeteer-21.11.0
# ✅ Actually exists
image: browserless/chrome:1-puppeteer-21.9.0
Latest vs stable tags:
latest = moving target (breaks in production)Version formats vary by project:
v3.3.21, others use 3.3.212024-01-15Workflow:
# 1. Find available versions
curl -s "https://registry.hub.docker.com/v2/repositories/IMAGE/tags?page_size=100" | jq -r '.results[].name'
# 2. Pick stable version (not :latest)
# 3. Test pull locally
docker pull IMAGE:VERIFIED_TAG
# 4. Pin in compose/Dockerfile
# 5. Document why that version was chosen
# Force kill
docker kill <container-id>
# If stuck, restart Docker daemon
# OrbStack: Quit + Reopen
Image size:
Build speed:
export DOCKER_BUILDKIT=1)Developer experience:
Security:
docker scout cves scansVersion pinning:
:latest tags in productionFROM python:3.12-slim
RUN pip install uv
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system -r requirements.txt
COPY . .
CMD ["python", "app.py"]
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci --only=production
FROM node:20-alpine
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
USER node
CMD ["node", "index.js"]
FROM rust:1.75-alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /app
COPY Cargo.* ./
RUN --mount=type=cache,target=/usr/local/cargo/registry \
cargo build --release
FROM scratch
COPY --from=builder /app/target/release/myapp /myapp
ENTRYPOINT ["/myapp"]
Optimizing image size?
→ dive myimage:latest → Fix top 5 wasted files → Alpine base → Multi-stage
Slow builds? → Check layer order → Add cache mounts → Enable BuildKit → Parallel stages
Debugging containers?
→ lazydocker → View logs/stats → Exec shell → Check health
Writing Dockerfile?
→ See ~/.claude/references/docker-best-practices.md → Test with dive → Iterate
Security review?
→ docker scout cves → Non-root user → No secrets → Update base image
documentation
Enrich Markdown articles with inline Wikipedia links. First mention of each notable entity gets a hyperlink. Use when asked to add wiki links, enrich, or add references to .md files.
development
Structured visual QA: screenshot → batch issues → fix all → verify. Replaces the 300-cycle screenshot→edit death spiral. Optional bishkek review as exit gate. Use when building/polishing UI with browser testing, or when user asks for N iterations/reviews.
development
Find complex code, analyze intent, recommend battle-tested library replacements. Uses radon/eslint for detection, GitHub quality search for alternatives.
research
Research real-world UI patterns from curated galleries (Collect UI, Component Gallery, Mobbin). Use when exploring what exists: dropdowns, accordions, inputs, navigation, cards, modals, etc.