Agent skill
app-docker-deploy-with-traefik
Generate Docker and Traefik deployment configurations for any application (Node.js, Python, Go, Rust, Java). Creates Dockerfile, docker-compose.yml, docker-compose.for-traefik.yml overlay, and .env.sample with production best practices. Use when: dockerize app, containerize, add Docker, deploy with Traefik, reverse proxy setup, HTTPS/SSL, Let's Encrypt certificates, production deployment, docker-compose setup. Requires: Docker, docker-compose.
Install this agent skill to your Project
npx add-skill https://github.com/yorch/claude-skills/tree/main/app-docker-deploy-with-traefik
SKILL.md
Docker + Traefik Deployment Setup
Generate production-ready Docker deployment configurations with Traefik reverse proxy integration, automatic HTTPS via Let's Encrypt.
Overview
This skill creates a deployment configuration following a proven pattern:
- Dockerfile - Multi-stage build for the application
- docker-compose.yml - Base service definitions
- docker-compose.for-traefik.yml - Traefik routing overlay (composable)
- .env.sample - Environment variable template
Instructions
Step 1: Analyze the Project
Before generating configurations, understand the project:
-
Detect the project type by examining:
package.json→ Node.js/TypeScriptrequirements.txt/pyproject.toml/Pipfile→ Pythongo.mod→ GoCargo.toml→ Rustpom.xml/build.gradle→ Java
-
Identify the application port from:
- Start scripts in package.json
- Application configuration files
- Common defaults (3000 for Node, 8000 for Python, 8080 for Go/Java)
-
Check for existing Docker files - Don't overwrite without asking
Step 2: Generate Dockerfile
Create a multi-stage Dockerfile appropriate for the project type. See DOCKERFILES.md for templates.
Key principles:
- Use official base images with specific version tags (not
:latest) - Multi-stage builds to minimize final image size
- Non-root user for security
- Proper layer caching (dependencies before source code)
- Health checks when appropriate
Step 3: Generate docker-compose.yml
Base configuration with:
- Service definitions for app and dependencies (db, redis, etc.)
- Volume mounts for persistent data (
./data/<service>:/path) - Environment variable references (
${VARIABLE}) - Restart policy:
unless-stopped - Health checks where appropriate
- Watchtower labels for auto-updates (optional)
services:
app:
build: .
restart: unless-stopped
volumes:
- ./data/app:/app/data
environment:
- NODE_ENV=${NODE_ENV}
- PORT=${PORT}
depends_on:
- db
labels:
- 'com.centurylinklabs.watchtower.enable=true'
- 'com.centurylinklabs.watchtower.scope=${WATCHTOWER_SCOPE}'
db:
image: postgres:17-alpine
restart: unless-stopped
volumes:
- ./data/postgres:/var/lib/postgresql/data
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
healthcheck:
test: pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"
interval: 10s
timeout: 2s
retries: 10
Step 4: Generate docker-compose.for-traefik.yml
Traefik overlay that can be composed with the base file:
services:
app:
networks:
- default
- traefik
labels:
- 'traefik.enable=true'
- 'traefik.docker.network=traefik'
# Service (internal port)
- 'traefik.http.services.${SERVICE_NAME}.loadbalancer.server.port=${PORT}'
# HTTPS Router
- 'traefik.http.routers.${SERVICE_NAME}.rule=Host(`${DOMAIN}`)'
- 'traefik.http.routers.${SERVICE_NAME}.entrypoints=websecure'
- 'traefik.http.routers.${SERVICE_NAME}.tls=true'
- 'traefik.http.routers.${SERVICE_NAME}.tls.certResolver=webcert'
- 'traefik.http.routers.${SERVICE_NAME}.service=${SERVICE_NAME}'
db:
networks:
- default
networks:
traefik:
external: true
Step 5: Generate .env.sample
Template for required environment variables:
# Domain and Deployment
DOMAIN=myapp.example.com
PORT=3000
# Database
POSTGRES_DB=myapp
POSTGRES_USER=myapp
POSTGRES_PASSWORD=change-me-in-production
# Application
NODE_ENV=production
# Auto-updates (optional)
WATCHTOWER_SCOPE=myapp
Step 6: Provide Usage Instructions
Include in the output:
- How to copy and configure .env
- How to run without Traefik (development)
- How to run with Traefik (production)
- Prerequisites (external traefik network)
Usage Commands
# Development (without Traefik)
docker compose up -d
# Production (with Traefik)
docker compose -f docker-compose.yml -f docker-compose.for-traefik.yml up -d
# Create external traefik network (first time only)
docker network create traefik
Traefik Label Reference
| Label | Purpose |
|---|---|
traefik.enable=true |
Enable Traefik routing for this container |
traefik.docker.network=traefik |
Specify which network Traefik should use |
traefik.http.services.NAME.loadbalancer.server.port=PORT |
Container's internal port |
traefik.http.routers.NAME.rule=Host(\domain`)` |
Domain routing rule |
traefik.http.routers.NAME.entrypoints=websecure |
Use HTTPS entrypoint |
traefik.http.routers.NAME.tls=true |
Enable TLS |
traefik.http.routers.NAME.tls.certResolver=webcert |
Use Let's Encrypt |
traefik.http.routers.NAME.service=NAME |
Link router to service |
Optional: Basic Auth Middleware
For admin panels or protected routes:
labels:
# Define middleware
- 'traefik.http.middlewares.myapp-auth.basicauth.users=${USERNAME}:${HASHED_PASSWORD}'
# Apply to router
- 'traefik.http.routers.myapp.middlewares=myapp-auth@docker'
Generate password hash: htpasswd -nb username password
Optional: Multiple Domains/Subdomains
# API subdomain
- 'traefik.http.routers.myapp-api.rule=Host(`api.${DOMAIN}`)'
- 'traefik.http.routers.myapp-api.entrypoints=websecure'
- 'traefik.http.routers.myapp-api.tls=true'
- 'traefik.http.routers.myapp-api.tls.certResolver=webcert'
- 'traefik.http.routers.myapp-api.service=myapp'
Best Practices
- Use specific image tags - Never use
:latestin production - External database volumes - Persist data outside containers
- Secrets management - Use Docker secrets for production passwords
- Health checks - Enable for proper orchestration
- Resource limits - Add memory/CPU limits in production
- Logging - Configure appropriate log drivers
- Non-root users - Run containers as non-root when possible
Helper Scripts
Located in the scripts/ directory:
generate-htpasswd.sh
Generate password hashes for Traefik basic auth:
./scripts/generate-htpasswd.sh admin mypassword
validate-compose.py
Validate docker-compose files for common issues:
python scripts/validate-compose.py docker-compose.yml docker-compose.for-traefik.yml
Requires: pip install pyyaml
check-network.sh
Check if the traefik network exists (and optionally create it):
./scripts/check-network.sh # Check only
./scripts/check-network.sh --create # Create if missing
Template Files
Located in the templates/ directory. Copy and customize:
| Template | Description |
|---|---|
Dockerfile.node |
Node.js multi-stage build |
Dockerfile.python |
Python with uv package manager |
docker-compose.yml |
Base compose with app + PostgreSQL |
docker-compose.for-traefik.yml |
Traefik routing overlay |
.dockerignore |
Optimized Docker build context |
.env.sample |
Environment variables template |
Replace placeholders: {{SERVICE_NAME}}, {{PORT}}, {{NODE_VERSION}}, etc.
Additional Resources
- DOCKERFILES.md - Complete Dockerfile templates for all languages
- EXAMPLES.md - Real-world deployment examples
Requirements
- Docker >= 20.10
- Docker Compose >= 2.0 (V2 syntax)
- Traefik >= 2.0 (running with
webcertcertificate resolver) - External
traefiknetwork:docker network create traefik
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
typescript-unknown-jsx-expression
Fix TypeScript error "Type 'unknown' is not assignable to type ReactNode" when using Record<string, unknown> values directly in JSX && short-circuit expressions. Use when: (1) JSX expression {someObj.field && <Component />} fails with TS2322, (2) Reading from a JSON or untyped object via bracket notation in JSX conditionals, (3) Values typed as unknown appear in JSX even when wrapped in String() or guarded with truthiness checks. Fix: use !! to coerce to boolean before the && operator.
gha-docker-publish
ALWAYS invoke this skill before writing any GitHub Actions workflow that builds or pushes Docker images — it contains specific opinionated patterns that produce secure, reliable workflows and that you cannot reliably guess. The conventions it enforces include: (1) datetime+SHA image tags in YYYYMMDDHHMMSS_sha format for unambiguous build traceability, (2) a `workflow_dispatch` boolean `push` input that defaults to `false` (safe dry-run by default — a common mistake is using `type:choice` with `dry_run` inversion instead), (3) a `publish-docker` PR label gate that lets CI validate builds on PRs without pushing, (4) conditional `latest` tag using `enable={{is_default_branch}}` (never hardcoded `enable=true`), (5) GHA layer cache with `mode=max` for maximum rebuild speed, (6) no inline `${{ github.sha }}` in `run:` scripts (security hardening), (7) dual-registry login and push patterns when publishing to both GHCR and a private registry. Use this whenever the user asks to: set up GHCR publishing, add a docker-publish.yml workflow, add layer caching to Docker CI, configure datetime/SHA image tags, add a manual build-only dispatch trigger, push to multiple registries, or build Docker images on PRs.
prisma-7-docker-migrations
Run Prisma 7 migrations inside a multi-stage Docker production image. Use when: (1) `prisma migrate deploy` crashes with "Cannot resolve environment variable: DATABASE_URL" or "cannot find module" at container startup, (2) building a production Docker image that needs to run migrations before starting the server, (3) you copied only node_modules/prisma + node_modules/@prisma but the Prisma 7 CLI still fails with MODULE_NOT_FOUND at runtime, (4) Yarn 4 node-modules linker .bin/prisma symlink breaks after Docker COPY. Covers prisma.config.ts (Prisma 7), full node_modules copy requirement, and symlink recreation pattern.
code-changes-review
Perform a comprehensive code review of current uncommitted changes in a git repository. Analyzes for bugs, security vulnerabilities, best practices, DRY violations, code smells, performance issues, and areas of improvement. Use when: review changes, code review, check my code, review diff, pre-commit review, PR review, quality check. Works with any language or framework.
rails-auto-assigned-field-validation
Fix for Rails models where validates :field, presence: true causes ALL creates to fail when the field is set by a before_create callback. Use when: (1) validates :number, presence: true is added to a model that uses before_create to auto-assign a sequence number, (2) model creates silently fail with "number can't be blank", (3) auto-generated fields (number, slug, token) fail presence validation despite being set in callbacks. Root cause: before_create runs AFTER validations. Fix: change before_create to before_validation on: :create.
edit-article
Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
Didn't find tool you were looking for?