agentsclimarketplace

Docker workflows

Skill Goodsmileduck/claude-registry/plugins/kubernetes-skills/skills/docker-workflows

Reviews and hardens Dockerfiles and docker-compose files — multi-stage build conversion, base-image choice, layer caching, secret leakage, root-user containers, missing healthchecks. Use when reviewing a Dockerfile, optimizing image size or build time, writing a compose file, or auditing container security.From its SKILL.md

Install
npx -y skills add Goodsmileduck/claude-registry --skill docker-workflows

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 2 commands, including `python3 "$SKILL/scripts/dockerfile_analyzer.py" Dockerfile` and 1 more.

SKILL.md

7.3 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it

Docker — Dockerfile and compose review

For Kubernetes manifests and pod debugging, see the kubernetes-operations skill. For Helm charts, see kubernetes-operators (if shipped as an operator) or chart-specific tooling.

When to invoke

Open with the static analyzers — they're stdlib Python, fast, deterministic:

SKILL=plugins/kubernetes-skills/skills/docker-workflows
python3 "$SKILL/scripts/dockerfile_analyzer.py" Dockerfile
python3 "$SKILL/scripts/compose_validator.py" docker-compose.yml

Both accept --output json for piping. dockerfile_analyzer.py --security narrows to security findings only. compose_validator.py --strict fails on warnings.

Read the findings before suggesting changes. The analyzer surfaces ~80% of routine issues; reserve LLM judgment for the rest.

Pre-flight: what's the image FOR?

Image strategy follows the workload, not vice versa.

WorkloadBase image defaultWhy
Compiled binary (Go, Rust)gcr.io/distroless/static-debian12 or scratchNo shell, no libc — tiny attack surface
Compiled w/ glibc deps (CGo)gcr.io/distroless/base-debian12Has glibc + ca-certs, no shell
Pythonpython:3.X-slim (Debian)Alpine's musl breaks many wheels (pandas, lxml)
Node.jsnode:X-alpinemusl is fine for pure JS; switch to slim if native modules struggle
Javaeclipse-temurin:X-jre-alpineJRE-only, not JDK, in runtime stage
Need a shell for prod debug*-slim variantdistroless = no sh, no kubectl exec shell

Pin the tag. :latest is a moving target — pin to python:3.12.7-slim (full version) or digest (python@sha256:...) for CI reproducibility.

Dockerfile anti-patterns (high → low severity)

PatternWhy it's wrongFix
Container runs as rootDefault UID 0 inside the container; if it escapes namespace, host rootRUN adduser -D app && USER app
Secret in ENV or ARGBaked into a layer; visible in docker history foreverBuildKit --mount=type=secret,id=..., read inside RUN
COPY . . before COPY package.json && RUN installAny source change busts the dep-install cacheCopy lockfile, install, then copy source
RUN apt-get install without cleanup in same layer/var/lib/apt/lists/* stays in the layer&& rm -rf /var/lib/apt/lists/* in the same RUN
Single-stage build for compiled codeShips SDK + source + build tools in final imageMulti-stage: builder + minimal runtime
No HEALTHCHECKOrchestrators can't tell "starting" from "broken"Add a cheap HTTP/exec check
:latest tag on baseReproducibility gone; today's build ≠ yesterday'sPin version, ideally digest
EXPOSE of ports the app doesn't bindMisleading documentation; no security impact but noiseMatch EXPOSE to actual LISTEN
ADD https://... for tarballsADD doesn't validate checksums`RUN curl -fsSL ...
chmod 777 anywhereAlmost always wrongchown + specific mode

Multi-stage patterns

Go (compiled, static)

FROM golang:1.23-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags='-s -w' -o /out/app ./cmd/app

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

Node.js

FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

FROM deps AS build
COPY . .
RUN npm run build && npm prune --omit=dev

FROM node:20-alpine
WORKDIR /app
RUN addgroup -S app && adduser -S -G app app
COPY --from=build --chown=app:app /app/dist ./dist
COPY --from=build --chown=app:app /app/node_modules ./node_modules
COPY --from=build --chown=app:app /app/package.json ./
USER app
EXPOSE 3000
HEALTHCHECK CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]

Python

FROM python:3.12-slim AS build
WORKDIR /app
RUN pip install --no-cache-dir --upgrade pip
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
RUN useradd -r -u 1001 app
COPY --from=build /install /usr/local
COPY --chown=app:app . .
USER app
EXPOSE 8000
HEALTHCHECK CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

BuildKit features worth using

  • --mount=type=cache,target=/root/.cache/pip — persistent dep cache between builds.
  • --mount=type=secret,id=npmrc,target=/root/.npmrc — secret available only inside one RUN, never written to a layer.
  • --platform=$BUILDPLATFORM + --platform=$TARGETPLATFORM — cross-compile from a fast builder.

Enable with DOCKER_BUILDKIT=1 (or in docker-bake.hcl/GitHub Actions buildx).

docker-compose review checklist

Run compose_validator.py first. Then read the file with this filter:

ConcernWhat to look for
Healthchecks presentEvery service that another service depends_on should have a healthcheck: + condition: service_healthy in the dependent's depends_on
Networks explicitBackend network with internal: true, frontend network for public services; never rely on the default bridge
Volumes named, not bindBind mounts (./data:/data) leak host paths; use named volumes for state
restart: setunless-stopped for prod-like, no for dev
Resource limitsmem_limit, cpus — without these one service can OOM the host
Env from fileenv_file: .env over inline environment: for anything secret; .env in .gitignore
Pinned image tagsSame :latest rule applies
docker-compose.override.yml for devHot-reload mounts, debug ports — keep dev concerns out of the prod compose

Proactive triggers

Flag these without being asked:

  • FROM ...:latest → pin to a version tag, ideally a digest.
  • COPY . . before any dependency-install RUN → cache bust. Reorder.
  • No USER instruction → container runs as root. Add a non-root user.
  • Secrets in ENV / ARG → BuildKit secret mounts. Never bake.
  • No .dockerignore → at minimum exclude .git, node_modules, __pycache__, .env, dist, build.
  • apt-get install without rm -rf /var/lib/apt/lists/* in the same RUN → cache stays in the layer.
  • Single-stage build for a compiled language → multi-stage with distroless runtime.
  • Compose service depends_on without condition: service_healthy → startup race; the dependent starts as soon as the container exists, not when it's ready.

What this skill does NOT cover

  • Container runtime internals (cgroups, namespaces, seccomp profiles beyond defaults). Image scanning beyond Dockerfile static checks — use Trivy/Grype.
  • Registry workflows (push/pull/signing). See digitalocean-registry-cleanup (in the digitalocean-skills plugin) for DigitalOcean registry hygiene.
  • Kubernetes-specific manifest concerns. See kubernetes-operations.

What ships with it: 2 files

25.5 KB alongside SKILL.md, 2 of them executable

scripts/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.