Dockerfile and CI Generator
Generate from what the repo actually is, verify by building and running, and leave the team with a fast, cacheable pipeline they can read.
Step 1 — Detect the stack
Look for: package.json (+ lockfile → npm/pnpm/yarn/bun), pyproject.toml/requirements.txt (uv/poetry/pip), go.mod, Cargo.toml, Gemfile, pom.xml/build.gradle, .NET csproj; frameworks (Next.js output: 'standalone', Django, FastAPI, Rails); required services (Postgres, Redis) from env examples; existing Dockerfile, .dockerignore, .github/workflows, Makefile. Note the runtime version from .nvmrc, .python-version, engines, or CI.
Ask only what the repo cannot tell you: target platform (Vercel/Fly/ECS/Kubernetes/VPS), registry, and whether the image must run as a specific user or on arm64.
Step 2 — Dockerfile principles
- Multi-stage:
deps→build→runtime. Copy only the artefacts the runtime needs. - Pin base images by tag and, ideally, digest:
node:22-bookworm-slim@sha256:…. Prefer slim/alpine/distroless for runtime; use the full image only in build stages. - Layer order for caching: copy lockfiles and manifest first, install dependencies, then copy source.
- Cache mounts:
RUN --mount=type=cache,target=/root/.npm npm ci(pnpm store, pip cache, cargo registry, go mod cache). - Non-root: create a user,
chownthe app dir,USER app. Expose the port withEXPOSE, and read it fromPORT. - Health:
HEALTHCHECK CMD curl -f http://localhost:$PORT/health || exit 1or the language equivalent. - Signals: use exec-form
CMD ["node", "server.js"]; addtinior--initif the app spawns children. .dockerignore:.git,node_modules,.env*, tests, docs, build outputs, IDE files.- No secrets in layers; use
--mount=type=secretfor private registries and build-time tokens. - Set
NODE_ENV=production,PYTHONDONTWRITEBYTECODE=1,PYTHONUNBUFFERED=1as appropriate.
Example skeleton (Node/pnpm):
# syntax=docker/dockerfile:1.7
FROM node:22-bookworm-slim AS base
RUN corepack enable