agentsclimarketplace

Dockerfile pro

Skill JayRHa/AgentSkills/dockerfile-pro

The largest community-driven library of Agent Skills (SKILL.md + scripts/references/examples) for Claude, Codex, Gemini CLI, Cursor and friends.

Install
npx -y skills add JayRHa/AgentSkills --skill dockerfile-pro

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

One thing to look at

  • 3 stars3 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.

What its author says it does

Copied from the file, not written here

Authors small, secure, reproducible multi-stage Dockerfiles with build-cache optimization, pinned base images, non-root runtime users, and minimal attack surface. Use this skill when writing, reviewing, hardening, or shrinking a Dockerfile or container image — e.g. "write a Dockerfile", "containerize this app", "my image is too big", "make this container secure / non-root", "optimize Docker build cache", "multi-stage build", "reduce image layers", "fix Docker best practices", or "review my Dockerfile".

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.5 KB, as published. Nobody here has run it

dockerfile-pro

Overview

Produce production-grade Dockerfiles that are small (minimal final image), secure (non-root, pinned, no secrets, minimal surface), and reproducible (deterministic builds with effective layer caching). Applies to any language runtime (Go, Rust, Node, Python, Java, .NET, etc.) and any registry.

Keywords: Dockerfile, container, multi-stage build, build cache, BuildKit, non-root user, distroless, alpine, slim, image size, layer caching, .dockerignore, HEALTHCHECK, OCI image, supply chain, reproducible build, hadolint, Trivy.

The three goals (small / secure / reproducible) often align, but when they conflict, prioritize security > reproducibility > size.

Workflow

Follow these steps in order when authoring or reviewing a Dockerfile.

  1. Identify the app shape. Compiled binary (Go/Rust/C++) → use a FROM scratch or distroless final stage. Interpreted/runtime (Node/Python/Java/.NET) → use the matching -slim/distroless runtime image. JVM/CLR may need a JRE-only final image.
  2. Always use multi-stage. A builder stage installs toolchains and compiles/installs dependencies; the final stage copies only the runtime artifacts. Never ship compilers, package caches, or dev headers.
  3. Pin everything. Pin the base image by tag and digest (image:tag@sha256:...). Pin OS and language package versions. This is what makes builds reproducible.
  4. Order layers from least- to most-frequently-changing. Copy dependency manifests (package.json, go.mod, requirements.txt, *.csproj) and install deps before copying application source. Source changes then don't bust the dependency layer.
  5. Use BuildKit cache mounts (RUN --mount=type=cache,...) for package-manager caches so repeated builds are fast without bloating the image.
  6. Drop to a non-root user in the final stage with an explicit numeric UID/GID. Make the filesystem read-only-friendly.
  7. Minimize layers and surface. Combine related RUN steps, clean package caches in the same layer, and copy with --chown instead of a separate chown layer.
  8. Add operational metadata. WORKDIR, EXPOSE, ENV, OCI LABELs, HEALTHCHECK, and an exec-form ENTRYPOINT/CMD.
  9. Add a .dockerignore. Exclude .git, node_modules, build output, secrets, and CI files so the build context stays small and secrets never enter an image.
  10. Lint and scan. Run hadolint Dockerfile and a vulnerability scan (e.g. trivy image). See scripts/check_dockerfile.py for a fast static audit you can run with zero dependencies.

Decision frameworks

Which final base image?

App typeRecommended final baseNotes
Static Go / Rust binarygcr.io/distroless/static or scratchAdd CA certs + /etc/passwd if using scratch.
Dynamically-linked binarygcr.io/distroless/base or *-slimNeeds libc.
Node.jsgcr.io/distroless/nodejs22-debian12 or node:22-slimDistroless has no shell — great for prod, harder to debug.
Pythonpython:3.12-slim or gcr.io/distroless/python3Prefer slim + venv copy.
Javaeclipse-temurin:21-jre or gcr.io/distroless/java21JRE only, never the JDK, in the final stage.
.NETmcr.microsoft.com/dotnet/aspnet:8.0 (or -chiseled)chiseled images are distroless-style and non-root by default.
Needs a shell/debug*-slim or *-alpineAlpine uses musl — watch for glibc-specific bugs.

Rule of thumb: distroless or scratch for compiled apps; -slim for interpreted apps. Avoid full :latest / fat base images.

Alpine vs slim?

  • Alpine: smallest, but musl libc can break native deps (Python wheels, glibc binaries) and complicate DNS/locale handling.
  • Debian -slim: slightly larger but maximally compatible. Default to -slim unless you have measured a real size win and tested compatibility.

Best Practices

  • Pin base by digest: FROM node:22.11.0-slim@sha256:<digest>. Tags are mutable; digests are not.
  • One concern per stage, named with AS builder, AS deps, AS runtime.
  • Exec form only: CMD ["node","server.js"] — never the shell form CMD node server.js (it breaks signal handling and PID 1 semantics).
  • Non-root with numeric UID: USER 10001:10001. A numeric UID lets Kubernetes enforce runAsNonRoot even without /etc/passwd.
  • COPY --chown=10001:10001 to set ownership without an extra layer; never chmod -R 777.
  • Clean in the same layer: apt-get update && apt-get install -y --no-install-recommends X && rm -rf /var/lib/apt/lists/*.
  • --no-install-recommends (apt) / --no-cache (apk) / --frozen-lockfile (npm ci) for determinism.
  • Pass secrets via RUN --mount=type=secret, never ARG/ENV (they persist in image history and docker history leaks them).
  • Add HEALTHCHECK for long-running services so orchestrators can detect liveness.
  • Set WORKDIR explicitly; never rely on /.
  • Use tini or --init (or a runtime that reaps zombies) when your process spawns children.
  • See references/best-practices.md for the full annotated checklist and rationale.

Common Pitfalls

  • ❌ Running as root in the final image (the default). Always add USER.
  • ADD for local files — use COPY. Reserve ADD for remote URLs/tar auto-extraction (and prefer not to).
  • ❌ Secrets in ARG/ENV or copied .env files — they leak via docker history and image layers.
  • apt-get upgrade / unpinned latest — destroys reproducibility.
  • ❌ Separate RUN chmod/chown after COPY — doubles the data on disk across layers. Use COPY --chown.
  • ❌ Copying the whole context first (COPY . .) before installing deps — busts the cache on every source edit.
  • ❌ Shell-form CMD/ENTRYPOINT — your process won't receive SIGTERM, so graceful shutdown breaks.
  • ❌ No .dockerignore — bloats context, slows builds, risks leaking .git/credentials.
  • ❌ Shipping the build toolchain in the final image — keep it in the builder stage only.

Supporting files

  • references/best-practices.md — exhaustive, annotated best-practice checklist with rationale, BuildKit cache-mount and secret-mount recipes, and a security/supply-chain section.
  • examples/go-multistage.Dockerfile — minimal scratch-based Go image (non-root, pinned, static).
  • examples/node-multistage.Dockerfile — Node.js multi-stage with npm ci, cache mounts, distroless final.
  • examples/python-multistage.Dockerfile — Python slim with venv copy and non-root user.
  • templates/Dockerfile.template — language-agnostic fill-in-the-blanks multi-stage template.
  • templates/dockerignore.template — sensible default .dockerignore.
  • scripts/check_dockerfile.py — zero-dependency static auditor that flags root users, unpinned bases, secrets in ARG, shell-form CMD, missing .dockerignore, and more.

Use the examples/templates as the starting skeleton, then apply the workflow and run scripts/check_dockerfile.py plus hadolint before finishing.

Keep looking

Skills are one crate of 328,083. 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.