Docker Composer
Creates optimized, production-ready Dockerfiles and docker-compose configurations for detected application stacks, including multi-stage builds for minimal image sizes, proper layer caching, health checks, and security hardening.
When to Use
- User asks to "dockerize this app", "create a Dockerfile", or "set up docker-compose"
- An existing Dockerfile is inefficient (large image, slow builds, running as root)
- A multi-service application needs a docker-compose setup for local development
- User wants to add a Docker setup for CI or deployment
- User asks for multi-stage builds to separate build and runtime environments
- Container image size or build time needs to be reduced
Process
Detect the application stack:
- Check for
package.json (Node.js), requirements.txt/pyproject.toml (Python), go.mod (Go), pom.xml/build.gradle (Java), Gemfile (Ruby), Cargo.toml (Rust)
- Note the framework (Express, FastAPI, Spring Boot, etc.)
- Identify if it's a static site, API server, worker process, or full-stack app
Choose the right base image:
- Prefer official slim/alpine variants:
node:20-slim, python:3.12-slim, golang:1.22-alpine
- For final runtime stages, use distroless where possible (
gcr.io/distroless/nodejs20-debian12)
- Pin to a specific digest or version tag — never use
latest
- Note the trade-offs (alpine uses musl vs. glibc which can affect native modules)
Design the multi-stage build:
- Stage 1 (deps/builder): install all dependencies, run build tools
- Stage 2 (runtime): copy only the compiled artifacts and runtime dependencies
- This keeps the final image free of build tools, source code, and dev dependencies
Apply layer caching optimization:
- Copy dependency manifests (
package.json, requirements.txt) BEFORE source code
- Run dependency install BEFORE copying application source
- This ensures the expensive install step is cached unless dependencies change
Security hardening:
- Create and use a non-root user (UID 1000):
RUN adduser --system appuser && USER appuser
- Set
WORKDIR explicitly
- Use
COPY --chown=appuser:appuser to set ownership
- Avoid
sudo, apt-get upgrade, or installing unnecessary packages
- Set
--no-cache for apk add / --no-install-recommends for apt-get
- Expose only necessary ports
Add health check: HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:${PORT}/health || exit 1
For docker-compose:
- Define services, networks, and named volumes
- Map ports and environment variables
- Set
depends_on with condition: service_healthy for database readiness
- Include development overrides (
docker-compose.override.yml) for hot reload
Generate a .dockerignore to exclude node_modules, .git, test files, and local config.
Output Format
# Dockerfile
# ── Stage 1: Dependencies ──────────────────────────────────────────────────────
FROM node:20-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
# ── Stage 2: Builder ──────────────────────────────────────────────────────────
FROM node:20-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# ── Stage 3: Runtime ──────────────────────────────────────────────────────────
FROM node:20-slim AS runtime
ENV NODE_ENV=production PORT=3000
WORKDIR /app
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
COPY --from=deps --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --chown=appuser:appgroup package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
Examples
Example Input
Dockerize a FastAPI Python app. It needs PostgreSQL and Redis.
Dev setup with hot reload. Production build should be minimal.
Example Output (summary)
Files generated:
Dockerfile — multi-stage: python:3.12-slim builder → distroless runtime
docker-compose.yml — services: app, postgres:16, redis:7-alpine
volumes: postgres_data, redis_data
networks: backend (internal), frontend (exposed)
docker-compose.override.yml — mounts ./src as volume, runs uvicorn --reload
.dockerignore — excludes __pycache__, .venv, .git, tests/, *.pyc
docker-compose.yml services:
app:
build: .
ports: ["8000:8000"]
env_file: .env
depends_on:
postgres: { condition: service_healthy }
redis: { condition: service_healthy }
postgres:
image: postgres:16-alpine
healthcheck: pg_isready
volumes: [postgres_data:/var/lib/postgresql/data]
redis:
image: redis:7-alpine
healthcheck: redis-cli ping
Boundaries
- Do NOT include secrets, passwords, or API keys in Dockerfiles or docker-compose.yml — always use environment variables and
.env files (which should be in .gitignore).
- Do NOT use
latest tag for base images in production Dockerfiles — always pin versions.
- Do NOT run container processes as
root unless absolutely necessary (and flag it clearly if required).
- Do NOT use
ADD with remote URLs — use COPY for local files and curl/wget in a RUN step.
- Warn if the application has native module dependencies that may be incompatible with Alpine's musl libc.
- Do NOT generate Kubernetes manifests from this skill — recommend the
api-scaffolder or dedicated K8s tooling.
- Always generate a
.dockerignore alongside the Dockerfile.
1---2name: docker-composer3description: Creates and validates Dockerfile and docker-compose.yml files optimized for the detected stack, including multi-stage builds. Invoke when asked to dockerize an application, create a Dockerfile, set up docker-compose, containerize a service, or optimize an existing Docker setup.4---56# Docker Composer78Creates optimized, production-ready Dockerfiles and docker-compose configurations for detected application stacks, including multi-stage builds for minimal image sizes, proper layer caching, health checks, and security hardening.910## When to Use1112- User asks to "dockerize this app", "create a Dockerfile", or "set up docker-compose"13- An existing Dockerfile is inefficient (large image, slow builds, running as root)14- A multi-service application needs a docker-compose setup for local development15- User wants to add a Docker setup for CI or deployment16- User asks for multi-stage builds to separate build and runtime environments17- Container image size or build time needs to be reduced1819## Process20211. **Detect the application stack**:22 - Check for `package.json` (Node.js), `requirements.txt`/`pyproject.toml` (Python), `go.mod` (Go), `pom.xml`/`build.gradle` (Java), `Gemfile` (Ruby), `Cargo.toml` (Rust)23 - Note the framework (Express, FastAPI, Spring Boot, etc.)24 - Identify if it's a static site, API server, worker process, or full-stack app25262. **Choose the right base image**:27 - Prefer official slim/alpine variants: `node:20-slim`, `python:3.12-slim`, `golang:1.22-alpine`28 - For final runtime stages, use distroless where possible (`gcr.io/distroless/nodejs20-debian12`)29 - Pin to a specific digest or version tag — never use `latest`30 - Note the trade-offs (alpine uses musl vs. glibc which can affect native modules)31323. **Design the multi-stage build**:33 - **Stage 1 (deps/builder)**: install all dependencies, run build tools34 - **Stage 2 (runtime)**: copy only the compiled artifacts and runtime dependencies35 - This keeps the final image free of build tools, source code, and dev dependencies36374. **Apply layer caching optimization**:38 - Copy dependency manifests (`package.json`, `requirements.txt`) BEFORE source code39 - Run dependency install BEFORE copying application source40 - This ensures the expensive install step is cached unless dependencies change41425. **Security hardening**:43 - Create and use a non-root user (UID 1000): `RUN adduser --system appuser && USER appuser`44 - Set `WORKDIR` explicitly45 - Use `COPY --chown=appuser:appuser` to set ownership46 - Avoid `sudo`, `apt-get upgrade`, or installing unnecessary packages47 - Set `--no-cache` for `apk add` / `--no-install-recommends` for `apt-get`48 - Expose only necessary ports49506. **Add health check**: `HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:${PORT}/health || exit 1`51527. **For docker-compose**:53 - Define services, networks, and named volumes54 - Map ports and environment variables55 - Set `depends_on` with `condition: service_healthy` for database readiness56 - Include development overrides (`docker-compose.override.yml`) for hot reload57588. **Generate a `.dockerignore`** to exclude `node_modules`, `.git`, test files, and local config.5960## Output Format6162```dockerfile63# Dockerfile64# ── Stage 1: Dependencies ──────────────────────────────────────────────────────65FROM node:20-slim AS deps66WORKDIR /app67COPY package.json package-lock.json ./68RUN npm ci --only=production6970# ── Stage 2: Builder ──────────────────────────────────────────────────────────71FROM node:20-slim AS builder72WORKDIR /app73COPY package.json package-lock.json ./74RUN npm ci75COPY . .76RUN npm run build7778# ── Stage 3: Runtime ──────────────────────────────────────────────────────────79FROM node:20-slim AS runtime80ENV NODE_ENV=production PORT=300081WORKDIR /app8283RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser8485COPY --from=deps --chown=appuser:appgroup /app/node_modules ./node_modules86COPY --from=builder --chown=appuser:appgroup /app/dist ./dist87COPY --chown=appuser:appgroup package.json ./8889USER appuser90EXPOSE 300091HEALTHCHECK --interval=30s --timeout=5s --retries=3 \92 CMD curl -f http://localhost:3000/health || exit 19394CMD ["node", "dist/server.js"]95```9697## Examples9899### Example Input100```101Dockerize a FastAPI Python app. It needs PostgreSQL and Redis.102Dev setup with hot reload. Production build should be minimal.103```104105### Example Output (summary)106```107Files generated:108 Dockerfile — multi-stage: python:3.12-slim builder → distroless runtime109 docker-compose.yml — services: app, postgres:16, redis:7-alpine110 volumes: postgres_data, redis_data111 networks: backend (internal), frontend (exposed)112 docker-compose.override.yml — mounts ./src as volume, runs uvicorn --reload113 .dockerignore — excludes __pycache__, .venv, .git, tests/, *.pyc114115docker-compose.yml services:116 app:117 build: .118 ports: ["8000:8000"]119 env_file: .env120 depends_on:121 postgres: { condition: service_healthy }122 redis: { condition: service_healthy }123 postgres:124 image: postgres:16-alpine125 healthcheck: pg_isready126 volumes: [postgres_data:/var/lib/postgresql/data]127 redis:128 image: redis:7-alpine129 healthcheck: redis-cli ping130```131132## Boundaries133134- Do NOT include secrets, passwords, or API keys in Dockerfiles or docker-compose.yml — always use environment variables and `.env` files (which should be in `.gitignore`).135- Do NOT use `latest` tag for base images in production Dockerfiles — always pin versions.136- Do NOT run container processes as `root` unless absolutely necessary (and flag it clearly if required).137- Do NOT use `ADD` with remote URLs — use `COPY` for local files and `curl`/`wget` in a `RUN` step.138- Warn if the application has native module dependencies that may be incompatible with Alpine's musl libc.139- Do NOT generate Kubernetes manifests from this skill — recommend the `api-scaffolder` or dedicated K8s tooling.140- Always generate a `.dockerignore` alongside the Dockerfile.