# Dockerfile Generation

> Use when creating Dockerfiles, optimizing container images, or reviewing Docker configurations. Produces multi-stage, security-hardened builds with proper layer caching. Triggers on 'create Dockerfile', 'dockerize', 'optimize container'.

- Skill: `dtsong/dockerfile-generation` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add dtsong/dockerfile-generation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dtsong/dockerfile-generation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: dtsong (https://skillmd.com/u/dtsong)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/dtsong/dockerfile-generation

---


# Dockerfile Generation Skill

Generate production-ready Dockerfiles through iterative verification.

## Scope Constraints

- Read access to codebase for analysis; write access limited to Dockerfile and .dockerignore
- Executes `docker build` and `docker run` for verification only — no deployment or registry push
- Does not modify application source code or dependency files
- Does not configure CI/CD pipelines — delegates to cicd-generation skill

## Input Sanitization

- Base image names: alphanumeric, hyphens, dots, slashes, colons only — reject shell metacharacters and null bytes
- Port numbers: integers 1-65535 only
- File paths in COPY directives: reject `..` traversal and null bytes

## Core Principles

1. **Verification-first**: Examine codebase BEFORE adding ANY instruction
2. **Multi-arch**: Support amd64/arm64, no hardcoded paths
3. **No HEALTHCHECK**: Cannot verify health endpoints from code alone
4. **Multi-stage builds**: Builder stage → minimal runtime stage
5. **Security**: Non-root user (UID 10001+), pinned versions, no `:latest`
6. **Layer optimization**: Dependencies first, source second

## Process

### Step 1: Analyze Codebase

Before writing ANY Dockerfile instruction, verify:

```
[ ] Language/runtime detected (package.json, requirements.txt, go.mod, etc.)
[ ] Entry point identified (main file, start script)
[ ] Build command identified (if compilation needed)
[ ] Dependencies file location confirmed
[ ] Required environment variables documented
[ ] Exposed ports identified from code (NOT assumed)
```

### Step 2: Generate Dockerfile

**Structure:**
```dockerfile
# syntax=docker/dockerfile:1

# Build stage
FROM <base>:<pinned-version> AS builder
WORKDIR /app
# Install deps first (cache layer)
COPY <deps-file> .
RUN <install-deps>
# Copy source
COPY . .
RUN <build-command>

# Runtime stage
FROM <minimal-base>:<pinned-version>
WORKDIR /app

# Security: non-root user
RUN addgroup --gid 10001 appgroup && \
    adduser --uid 10001 --ingroup appgroup --disabled-password appuser
USER appuser

# Copy artifacts from builder
COPY --from=builder --chown=appuser:appgroup /app/<artifact> .

EXPOSE <verified-port>
CMD ["<verified-entrypoint>"]
```

**Language-specific bases:**
| Language | Builder | Runtime |
|----------|---------|---------|
| Node.js | `node:<version>-alpine` | `node:<version>-alpine` |
| Python | `python:<version>-slim` | `python:<version>-slim` |
| Go | `golang:<version>-alpine` | `gcr.io/distroless/static` |
| Java | `eclipse-temurin:<version>` | `eclipse-temurin:<version>-jre-alpine` |
| Rust | `rust:<version>-alpine` | `gcr.io/distroless/cc` |

### Step 3: Validation Loop (Max 5 iterations)

```bash
# Build
docker build -t test-image:local .

# Run and capture logs
docker run --rm test-image:local 2>&1 | head -50

# If error: analyze → fix → rebuild
# If success: verify functionality
```

**Stop conditions:**
- Container starts and responds correctly
- 5 iterations reached (escalate to user)

## Gotchas

- `COPY . .` before `COPY package*.json && npm install` busts the dependency cache on every source change — always copy deps files first
- Alpine-based images use `musl` not `glibc` — native Node.js addons (bcrypt, sharp) may fail with cryptic errors. Use `-slim` for compatibility
- `RUN apt-get update && apt-get install` without `rm -rf /var/lib/apt/lists/*` bloats the image by 30-100MB
- Multi-stage builds discard everything not explicitly `COPY --from=builder` — forgetting to copy a config file causes silent runtime failures
- `EXPOSE` is documentation only — it does NOT publish the port. You still need `-p` at runtime
- Running as root (default) means container compromise = full host access — always add a non-root user with UID 10001+

## Anti-patterns to Avoid

- `FROM <image>:latest` - Always pin versions
- `RUN apt-get update && apt-get install` without cleanup
- `COPY . .` before dependency installation
- Running as root
- Hardcoded secrets or credentials
- Assuming ports without code verification
- Adding HEALTHCHECK without verified endpoint

## Output Format

When generating a Dockerfile, output:

1. **Analysis summary**: What was detected in codebase
2. **Dockerfile**: The generated file
3. **Build command**: Exact command to build
4. **Run command**: Exact command to test
5. **Notes**: Any assumptions or manual verification needed

