Install
$ agentstack add skill-jayrha-agentskills-dockerfile-pro Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
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.
- Identify the app shape. Compiled binary (Go/Rust/C++) → use a
FROM scratchordistrolessfinal stage. Interpreted/runtime (Node/Python/Java/.NET) → use the matching-slim/distrolessruntime image. JVM/CLR may need a JRE-only final image. - Always use multi-stage. A
builderstage installs toolchains and compiles/installs dependencies; the final stage copies only the runtime artifacts. Never ship compilers, package caches, or dev headers. - 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. - 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. - Use BuildKit cache mounts (
RUN --mount=type=cache,...) for package-manager caches so repeated builds are fast without bloating the image. - Drop to a non-root user in the final stage with an explicit numeric UID/GID. Make the filesystem read-only-friendly.
- Minimize layers and surface. Combine related
RUNsteps, clean package caches in the same layer, and copy with--chowninstead of a separatechownlayer. - Add operational metadata.
WORKDIR,EXPOSE,ENV, OCILABELs,HEALTHCHECK, and an exec-formENTRYPOINT/CMD. - 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. - Lint and scan. Run
hadolint Dockerfileand a vulnerability scan (e.g.trivy image). Seescripts/check_dockerfile.pyfor a fast static audit you can run with zero dependencies.
Decision frameworks
Which final base image?
| App type | Recommended final base | Notes | |---|---|---| | Static Go / Rust binary | gcr.io/distroless/static or scratch | Add CA certs + /etc/passwd if using scratch. | | Dynamically-linked binary | gcr.io/distroless/base or *-slim | Needs libc. | | Node.js | gcr.io/distroless/nodejs22-debian12 or node:22-slim | Distroless has no shell — great for prod, harder to debug. | | Python | python:3.12-slim or gcr.io/distroless/python3 | Prefer slim + venv copy. | | Java | eclipse-temurin:21-jre or gcr.io/distroless/java21 | JRE only, never the JDK, in the final stage. | | .NET | mcr.microsoft.com/dotnet/aspnet:8.0 (or -chiseled) | chiseled images are distroless-style and non-root by default. | | Needs a shell/debug | *-slim or *-alpine | Alpine 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
musllibc can break native deps (Python wheels, glibc binaries) and complicate DNS/locale handling. - Debian
-slim: slightly larger but maximally compatible. Default to-slimunless you have measured a real size win and tested compatibility.
Best Practices
- Pin base by digest:
FROM node:22.11.0-slim@sha256:. 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 formCMD node server.js(it breaks signal handling and PID 1 semantics). - Non-root with numeric UID:
USER 10001:10001. A numeric UID lets Kubernetes enforcerunAsNonRooteven without/etc/passwd. COPY --chown=10001:10001to set ownership without an extra layer; neverchmod -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, neverARG/ENV(they persist in image history anddocker historyleaks them). - Add
HEALTHCHECKfor long-running services so orchestrators can detect liveness. - Set
WORKDIRexplicitly; never rely on/. - Use
tinior--init(or a runtime that reaps zombies) when your process spawns children. - See
references/best-practices.mdfor the full annotated checklist and rationale.
Common Pitfalls
- ❌ Running as root in the final image (the default). Always add
USER. - ❌
ADDfor local files — useCOPY. ReserveADDfor remote URLs/tar auto-extraction (and prefer not to). - ❌ Secrets in
ARG/ENVor copied.envfiles — they leak viadocker historyand image layers. - ❌
apt-get upgrade/ unpinnedlatest— destroys reproducibility. - ❌ Separate
RUN chmod/chownafterCOPY— doubles the data on disk across layers. UseCOPY --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 receiveSIGTERM, 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 withnpm 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.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: JayRHa
- Source: JayRHa/AgentSkills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.