skills/containerfile-creator/SKILL.md
Create high-quality, secure, and performance-optimized Containerfiles (Dockerfiles) following best practices for multi-architecture builds, OpenShift/Kubernetes compatibility, and BuildKit cache optimization. Use when the user wants to: (1) create a new Containerfile or Dockerfile for any project (Python, Rust, Go, Node.js, .NET, or any language), (2) containerize an application with multi-stage builds, (3) optimize an existing Containerfile for security, performance, or image size, (4) review or improve container image build practices, (5) set up BuildKit cache mounts for package managers, (6) create OpenShift-compatible container images with non-root users and arbitrary UID support, (7) write a .dockerignore file, or (8) apply OCI LABEL standards.
npx skillsauth add jim60105/copilot-prompt containerfile-creatorInstall 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.
Create secure, efficient, and maintainable container images following open source best practices.
Containerfile over Dockerfilealpine.Containerfile, distroless.Containerfile, ubi.ContainerfileEvery file MUST start with:
# syntax=docker/dockerfile:1
Only UID, VERSION, and RELEASE go at the top level:
# syntax=docker/dockerfile:1
ARG UID=1001
ARG VERSION=EDGE
ARG RELEASE=0
TARGETARCH and TARGETVARIANT MUST be declared inside each stage that uses them, not globally.
########################################
# Build stage
########################################
FROM python:3.13-alpine AS build
########################################
# Final stage
########################################
FROM python:3.13-alpine AS final
final# characters for stage separatorsbase stage when it requires non-trivial setup (e.g., installing system packages on UBI/Debian)Declare multi-arch variables inside each stage that uses cache mounts:
ARG TARGETARCH
ARG TARGETVARIANT
# Alpine APK
RUN --mount=type=cache,id=apk-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apk \
apk update && apk add -u package-name
# Debian/Ubuntu APT
RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \
--mount=type=cache,id=aptlists-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/lib/apt/lists \
apt-get update && apt-get install -y --no-install-recommends package-name
# Python PIP
RUN --mount=type=cache,id=pip-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/pip \
pip install package-name
# Python UV
RUN --mount=type=cache,id=uv-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/uv \
uv pip install package-name
# DNF (Fedora/RHEL)
RUN --mount=type=cache,id=dnf-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/dnf \
dnf -y install package-name
# Alpine
ARG UID
RUN adduser -g "" -D $UID -u $UID -G root
# Debian/Ubuntu
ARG UID
RUN groupadd -g $UID $UID && \
useradd -l -u $UID -g $UID -m -s /bin/sh -N $UID
# Create directories
RUN install -d -m 775 -o $UID -g 0 /app && \
install -d -m 775 -o $UID -g 0 /licenses
# Copy files with proper ownership
COPY --link --chown=$UID:0 --chmod=775 source dest
COPY --link --chown=$UID:0 --chmod=775 LICENSE /licenses/Containerfile.LICENSE
COPY --link --chown=$UID:0 --chmod=775 project/LICENSE /licenses/project.LICENSE
Use dumb-init as PID 1 for proper signal handling. Download in a separate stage with SHA256 verification:
########################################
# Download stage
########################################
FROM docker.io/library/debian:bookworm-slim AS download
ARG TARGETARCH
ARG TARGETVARIANT
RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \
--mount=type=cache,id=aptlists-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/lib/apt/lists \
apt-get update && apt-get install -y --no-install-recommends curl ca-certificates
# Download dumb-init static binary (arch-aware) with SHA256 verification
RUN case "${TARGETARCH}" in \
amd64) DUMBINIT_ARCH="x86_64"; DUMBINIT_SHA256="e874b55f3279ca41415d290c512a7ba9d08f98041b28ae7c2acb19a545f1c4df" ;; \
arm64) DUMBINIT_ARCH="aarch64"; DUMBINIT_SHA256="b7d648f97154a99c539b63c55979cd29f005f88430fb383007fe3458340b795e" ;; \
*) echo "unsupported architecture: ${TARGETARCH}" && exit 1 ;; \
esac && \
curl -fsSL "https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_${DUMBINIT_ARCH}" \
-o /dumb-init && \
echo "${DUMBINIT_SHA256} /dumb-init" | sha256sum -c -
Then copy in the final stage:
COPY --link --chown=$UID:0 --chmod=775 --from=download /dumb-init /usr/local/bin/dumb-init
When the application creates directories at runtime, use umask 0002 to preserve GID-0 group-write:
ENTRYPOINT ["dumb-init", "--"]
CMD ["sh", "-c", "umask 0002 && exec my-app"]
The exec replaces the shell so dumb-init's signal forwarding reaches the app directly.
Always use --link flag for COPY instructions to enable layer reuse across builds:
COPY --link --chown=$UID:0 --chmod=775 source dest
Do NOT use --link when destination path contains symlinks that need to be followed.
Follow this exact order in the final stage:
install -d)--link --chown=$UID:0 --chmod=775)LABEL MUST be the very last instruction. VERSION/RELEASE ARGs bust the cache for all subsequent instructions. Placing them last ensures maximum cache reuse.
ARG VERSION
ARG RELEASE
LABEL name="project-name" \
vendor="original-author" \
maintainer="user-id" \
url="https://github.com/user-id/project" \
version=${VERSION} \
release=${RELEASE} \
io.k8s.display-name="Display Name" \
summary="Brief summary" \
description="Detailed description with website reference"
HEALTHCHECK does not function in OCI/podman builds. Do NOT implement unless specifically requested.
When implementing:
COPY --link --from=ghcr.io/tarampampam/curl:8.7.1 /bin/curl /usr/local/bin/
HEALTHCHECK --interval=30s --timeout=2s --start-period=30s \
CMD [ "curl", "--fail", "http://localhost:8080/" ]
Run linting, type-checking, and tests inside the build. Use --mount=type=bind for test files to avoid caching them in layers:
########################################
# Test stage
########################################
FROM deps AS test
ARG TARGETARCH
ARG TARGETVARIANT
ENV PATH="/venv/bin${PATH:+:${PATH}}"
WORKDIR /app
# Install dev dependencies using separate cache to avoid conflicts
RUN --mount=type=cache,id=uv-test-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/uv \
--mount=type=bind,source=pyproject.toml,target=/app/pyproject.toml \
--mount=type=bind,source=uv.lock,target=/app/uv.lock \
uv sync --frozen --no-install-project
COPY src/ src/
# Run quality checks and tests with bind-mounted test files
RUN --mount=type=bind,source=tests,target=/app/tests \
--mount=type=bind,source=pyproject.toml,target=/app/pyproject.toml \
pytest --junit-xml=/app/test-results.xml \
--cov=src \
--cov-report=xml:/app/coverage.xml \
--cov-fail-under=70 \
--verbose
Extract test reports from the build without running the full image:
########################################
# Report stage
# How to: podman build --target report --output type=local,dest=./out .
########################################
FROM scratch AS report
ARG UID=1001
COPY --chown=$UID:0 --chmod=775 --from=test /app/test-results.xml /
COPY --chown=$UID:0 --chmod=775 --from=test /app/coverage.xml /
Extract reports locally:
podman build --target report --output type=local,dest=./out .
Export statically linked binaries from the build:
########################################
# Binary stage
# How to: podman build --output=. --target=binary .
########################################
FROM scratch AS binary
COPY --from=builder /app/binary /
Binary stage is only for statically linked binaries or self-contained outputs.
Install large, rarely changed packages first, then project-specific dependencies:
RUN uv pip install torch==2.7.0 tensorflow>=2.16.1
RUN uv pip install -r requirements.txt
**/node_modules
**/*.log
**/.git
**/.gitignore
**/.env
**/.github
**/.vscode
**/bin
**/obj
**/dist
**/tmp
Load the appropriate reference file based on the project's language/pattern:
development
Diátaxis Documentation Expert. An expert technical writer specializing in creating high-quality software documentation, guided by the principles and structure of the Diátaxis technical documentation authoring framework.
testing
Guide users through a structured workflow for co-authoring documentation. Use when user wants to write documentation, proposals, technical specs, decision docs, or similar structured content. This workflow helps users efficiently transfer context, refine content through iteration, and verify the doc works for readers. Trigger when user mentions writing docs, creating proposals, drafting specs, or similar documentation tasks.
tools
Comprehensive guide for building, configuring, customizing, and deploying Docsify documentation sites. Use when the user wants to (1) initialize a new Docsify site, (2) add or organize Markdown pages, sidebars, navbars, or cover pages, (3) configure `window.$docsify` options, (4) customize themes / CSS variables / fonts, (5) install built-in or third-party Docsify plugins (search, GA, emoji, zoom, copy-code, comments, pagination, tabs, etc.), (6) write a custom Docsify plugin using lifecycle hooks, (7) use Docsify Markdown helpers (callouts, link attributes, image attributes, heading IDs, task lists, embed files with `:include`), (8) deploy to GitHub Pages, GitLab Pages, Netlify, Vercel, Firebase, Docker, Nginx, etc., (9) enable PWA / offline mode, virtual routes, or Vue compatibility, or (10) upgrade a Docsify site from v4 to v5. Triggers on mentions of "docsify", "_sidebar.md", "_navbar.md", "_coverpage.md", "$docsify", or `docsify-cli`.
testing
Writing guidelines for producing high-quality Traditional Chinese (zh-TW) content. Use when writing any kind of content. Including blog posts, notes, technical articles, technical writing, chitchat, social media posts, etc., even when you are just sending a text message. Also use when reviewing or editing existing Chinese content for tone, style, and terminology compliance.