generate-dockerfile
Skill1 starsChanged 3 months agoMITView on GitHub
Use when the user asks to dockerize, containerize, or write a Dockerfile for a project, or an existing project has no Dockerfile — or has one that copies source before dependencies, runs as root, or ships a single oversized stage.
- Reads credentials
- Deletes or force-pushes
- Installs packages
2 other projects use a version of this.
Adopted by
Most recently taken up by
- vtmocanu/skillstheir own version, first seen Nov 7, 2026
- Azure/containerization-assisttheir own version, first seen Jun 8, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- Azure/containerization-assist★ 43same name
- vtmocanu/skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository58 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- api-test-suiteSkill
- ascii-artSkill
- caddy-reverse-proxySkill
- changelog-generatorSkill
- color-palette-generatorSkill
- cron-taskSkill
- csv-toolkitSkill
- discord-bot-buildSkill
- docker-umbrellaSkill
- dotfiles-manageSkill
- email-sendSkill
- env-config-managerSkill
- excalidraw-diagramSkill
- file-organizerSkill
- forgejo-self-hostSkill
- frontend-design-toolkitSkill
- gif-searchSkill
- git-backupSkill
- github-actions-ciSkill
- hallmark-readmeSkill
- http-api-testerSkill
- invoice-generatorSkill
- json-formatterSkill
- log-analyzerSkill
- markdown-linterSkill
- markdown-to-pdfSkill
- markdown-to-slidesSkill
- mcp-server-buildSkill
- media-id-mappingSkill
- movie-catalogue-siteSkill
- movie-night-calendarSkill
- ntfy-notifierSkill
- ocr-documentsSkill
- ollama-localSkill
- openapi-generatorSkill
- password-generatorSkill
- pdf-extractSkill
- portfolio-upkeepSkill
- qr-code-generatorSkill
- regex-testerSkill
- resume-builderSkill
- rss-monitorSkill
- searxng-self-hostSkill
- skill-publishSkill
- skill-registry-catalogSkill
- skills-portfolio-scaffoldSkill
- snippet-managerSkill
- sqlite-dashboardSkill
- streaming-provider-embedsSkill
- tailscale-deploySkill
- telegram-bot-buildSkill
- tmdb-metadataSkill
- uptime-kuma-self-hostSkill
- watchlist-syncSkill
- webhook-receiverSkill
- youtube-transcriptSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 1 is distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
Read a project, detect its stack, and emit a multi-stage Dockerfile plus the supporting files (.dockerignore, .env.example, …
- Very specific: line 42
Emit
.env.example: if the code reads env vars (database URLs, API keys, ports). - Very specific: line 44
Emit
docker-compose.yml: when the service has dependencies (Postgres, Redis, a sibling API). - Very specific: line 197
Always write this. It keeps build context small and stops .env from landing in the image.
- Distinctive: line 222
Write this only if the code reads environment variables.
- Very specific: line 232
Write this when the service has dependencies.
- Very specific: line 284
When you COPY source after creating the user, pass --chown=app:app (or the distroless nonroot) so the runtime user can read it.
- Very specific: line 294
Copying source before dependencies: If COPY . . comes before the dep install, every source edit invalidates the dependency layer and …
- Very specific: line 308
Host loopback on some setups: When testing from the host, prefer http://127.0.0.1:<port> over localhost — on some systems localhost …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
generate-dockerfile
Overview
Read a project, detect its stack, and emit a multi-stage Dockerfile plus the
supporting files (.dockerignore, .env.example, docker-compose.yml) needed
for a reproducible, small, non-root container build. The agent writes the files;
this skill carries the detection rules and the templates.
When to Use
- The user says "dockerize this", "write a Dockerfile", or "containerize my app".
- You are scaffolding a new project and it will be deployed as a container.
- An existing project has no Dockerfile, or has one that copies source before dependencies, runs as root, or ships a single oversized stage.
- You are setting up local development with multiple services (app + database +
cache) and need a
docker-compose.yml.
Workflow
- Inventory the project root. List files and read the manifest(s):
package.json,requirements.txt,pyproject.toml,Pipfile,go.mod,Cargo.toml,uv.lock,yarn.lock,pnpm-lock.yaml,index.html. - Detect the stack using the signals in the table below. One project can mix stacks (e.g. Node frontend + Python API) — generate one Dockerfile per deployable service, not one mega-image.
- Pick the matching template and adjust versions to the constraints you
found (Node
engines, Python version inpyproject.toml, Go toolchain). - Write
Dockerfileto the service root. Always write.dockerignorealongside it — without it the build context leaks.env,node_modules, and.gitinto the image. - Emit
.env.exampleif the code reads env vars (database URLs, API keys, ports). Never write real secrets into the image. - Emit
docker-compose.ymlwhen the service has dependencies (Postgres, Redis, a sibling API). Skip it for a standalone static site. - Verify by running
docker build(ordocker compose build) if Docker is available and the user wants validation. Otherwise hand back the files with the exact build command to run.
Stack Detection
| Stack | Primary signal(s) | Package manager |
| Node.js | package.json | npm / yarn / pnpm |
| Python (pip) | requirements.txt | pip |
| Python (poetry) | pyproject.toml with [tool.poetry] | poetry |
| Python (uv) | pyproject.toml + uv.lock | uv |
| Go | go.mod | go modules |
| Rust | Cargo.toml + Cargo.lock | cargo |
| Static site | index.html / SPA build output, no backend runtime | (none — nginx serves) |
Detection priority when multiple exist: a backend runtime manifest
(go.mod, Cargo.toml, pyproject.toml, requirements.txt) wins over a
frontend package.json. A package.json with only a build script and no
server start script is a static-site build step, not a Node service.
Dockerfile Templates
Python — pip (primary)
FROM python:3.12-slim AS builder
WORKDIR /app
ENV PIP_NO_CACHE_DIR=1 PIP_DISABLE_PIP_VERSION_CHECK=1
COPY requirements.txt ./
RUN pip wheel --no-cache-dir --wheel-dir /wheels -r requirements.txt
FROM python:3.12-slim AS runtime
WORKDIR /app
RUN groupadd --system app && useradd --system --gid app --home /app app
COPY --from=builder /wheels /wheels
COPY requirements.txt ./
RUN pip install --no-cache-dir --no-index --find-links /wheels -r requirements.txt \
&& rm -rf /wheels
COPY --chown=app:app . /app
USER app
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health')" || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]Poetry / uv differ only in how the dependency set is produced before the
install. Replace the builder stage's copy+install with:
- Poetry:
RUN pip install poetry→COPY pyproject.toml poetry.lock ./→RUN poetry config virtualenvs.create false && poetry export -f requirements.txt --without-hashes -o requirements.txt→ then the samepip wheelstep. - uv:
RUN pip install uv→COPY pyproject.toml uv.lock* ./→RUN uv pip compile -o requirements.txt pyproject.toml || true→ then the samepip wheelstep. (If you install straight into a venv target instead, drop the wheel stage.)
Node.js — npm (primary)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build
FROM node:20-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -S app && adduser -S app -G app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --ignore-scripts
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/public ./public
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget -q -O - http://127.0.0.1:3000/health || exit 1
CMD ["node", "dist/index.js"]Package-manager variants change the manifest copy and the install command:
| Manager | Manifest(s) copied | Install command (builder / runtime) |
| npm | package.json package-lock.json | npm ci --ignore-scripts / npm ci --omit=dev --ignore-scripts |
| yarn | package.json yarn.lock | yarn install --frozen-lockfile --ignore-scripts / --production |
| pnpm | package.json pnpm-lock.yaml | pnpm install --frozen-lockfile --ignore-scripts / --prod (needs corepack enable) |
Go (static binary)
FROM golang:1.22-alpine AS builder
WORKDIR /src
RUN apk add --no-cache git
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/bin ./cmd/server
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/bin /app/bin
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app/bin"]For a HEALTHCHECK under distroless you need a binary in the image, so either
add a small health subcommand to the server and call it from HEALTHCHECK, or
drop the HEALTHCHECK here and rely on the compose-level check.
Rust (static binary)
FROM rust:1.78 AS builder
WORKDIR /app
# Build dependencies first: the dummy crate lets Cargo cache the dep layer.
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs \
&& cargo build --release \
&& rm -rf src
COPY . .
RUN cargo build --release
FROM gcr.io/distroless/cc-debian12
COPY --from=builder /app/target/release/app /app/app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app/app"]Static site (SPA built with Node, served by nginx)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build
FROM nginx:1.27-alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget -q -O - http://127.0.0.1/ || exit 1For client-side routing (React/Vue history mode) the nginx.conf needs an
internal fallback to index.html:
server {
listen 80;
root /usr/share/nginx/html;
location / { try_files $uri $uri/ /index.html; }
}Supporting Files
.dockerignore
Always write this. It keeps build context small and stops .env from landing
in the image.
.git
.gitignore
node_modules
__pycache__
*.pyc
.venv
venv
dist
build
target
.env
.env.*
Dockerfile
docker-compose.yml
.dockerignore
*.md
.vscode
.idea
.DS_Store.env.example
Write this only if the code reads environment variables. Keep it secret-free.
# Copy to .env and fill in real values — never commit the filled-in .env.
DATABASE_URL=postgres://app:app@db:5432/app
REDIS_URL=redis://cache:6379
PORT=8000
LOG_LEVEL=infodocker-compose.yml
Write this when the service has dependencies. The depends_on + healthcheck
pattern avoids "container started but DB not ready" races.
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8000:8000"
env_file:
- .env
depends_on:
db:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: app
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
db_data:Health Checks
- Point the
HEALTHCHECKat a real endpoint the app actually serves (/health,/ready). Awgetagainst/that returns 200 for any HTML page hides a broken backend. wgetandcurlare not present indistrolessorslimPython by default. The Python template usespython -cfor the check; the Node/alpine and nginx templates usewget(present in-alpine).
Non-root User
- Alpine:
addgroup -S app && adduser -S app -G appthenUSER app. - Debian-slim:
groupadd --system app && useradd --system --gid app --home /app app. - distroless: the
nonrootuser already exists — justUSER nonroot:nonroot. - When you
COPYsource after creating the user, pass--chown=app:app(or the distrolessnonroot) so the runtime user can read it.
Common Pitfalls
npm installinstead ofnpm ci.npm cirequires a lockfile and installs exactly what it pins — reproducible.npm installcan drift. Usenpm ci,yarn install --frozen-lockfile, orpnpm install --frozen-lockfile.- Lifecycle scripts. Plain
npm cirunspostinstallscripts from dependencies. Default to--ignore-scriptsand only enable it for a specific package you have inspected. - Copying source before dependencies. If
COPY . .comes before the dep install, every source edit invalidates the dependency layer and re-downloads everything. Copy the manifest, install, then copy source. - Missing
.dockerignore. Without it,node_modules,.git, and.envget sent as build context and can be baked into the image. - Running as root. The default container user is root; add a non-root user in the runtime stage.
--latestbase tags. Pin (python:3.12-slim,node:20-alpine). Unpinned builds break unpredictably when upstream moves.- SPA
__dirnamelayout mismatch. A Node server that resolves a siblingfrontend/viapath.join(__dirname, '..', 'frontend')breaks when the Dockerfile copies the backend to/appand the frontend elsewhere — every static asset 404s while/api/*still works. Copy the frontend into the same directory the server expects and have the resolver try both candidate paths. - Host loopback on some setups. When testing from the host, prefer
http://127.0.0.1:<port>overlocalhost— on some systemslocalhostresolves to IPv6::1first and the request hangs even though the container is healthy. Confirm the app is alive from inside the container (docker compose exec app wget -q -O - http://127.0.0.1:8000/health) before blaming the code.
Verification Checklist
docker build -t <svc> .(ordocker compose build) succeeds and the final image is small- Container runs and the health endpoint responds from inside it
docker run --rm <svc> idreports a non-zero uid (not running as root)docker run --rm <svc> ls -la(or a build-context review) confirms no.envlanded in the image
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

