Claude-skill-registry dokploy-health-patterns
Health check patterns for different service types in Dokploy templates. Covers HTTP, PostgreSQL, MongoDB, Redis, MySQL, and custom health checks.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dokploy-health-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-dokploy-health-patterns && rm -rf "$T"
skills/data/dokploy-health-patterns/SKILL.mdDokploy Health Patterns
When to Use This Skill
- When adding health checks to any Dokploy service
- When configuring service dependencies with
service_healthy - When troubleshooting container startup order issues
- When user asks about "health checks" or "service dependencies"
When NOT to Use This Skill
- For services that don't support health checks (rare, most do)
- For helper services that start instantly (use
instead)service_started
Prerequisites
- Understanding of service internals (ports, health endpoints)
- Knowledge of available tools in container (curl, wget, etc.)
Core Pattern
Standard Health Check Template
Every health check follows this structure:
healthcheck: test: ["CMD", "command", "args"] interval: 30s # How often to check timeout: 10s # Max time per check retries: 3 # Failures before unhealthy start_period: 30s # Grace period for startup
Configuration Guidelines:
| Parameter | Default | When to Adjust |
|---|---|---|
| 30s | Increase for resource-constrained systems |
| 10s | Increase for slow-starting services |
| 3 | Increase for flaky services |
| 30s | Increase for complex services (databases, Java apps) |
Health Check Patterns by Service Type
Pattern 1: HTTP Services (curl)
For services with HTTP endpoints (most web apps):
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:${PORT}/"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Variations:
# With specific health endpoint test: ["CMD", "curl", "-f", "http://localhost:3000/health"] # With API endpoint test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"] # Silent output test: ["CMD", "curl", "-sf", "http://localhost:8080/ping"]
Pattern 2: HTTP Services (wget - Alpine-based)
For Alpine-based images without curl:
healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:${PORT}"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Example (Paaster):
healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Pattern 3: PostgreSQL
healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Variations:
# With specific host test: ["CMD-SHELL", "pg_isready -U postgres -d mydb -h localhost"] # With default user test: ["CMD-SHELL", "pg_isready -U postgres"] # With environment variable interpolation test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-postgres}"]
Pattern 4: MongoDB
healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Variations:
# For older MongoDB (pre-6.0, use mongo instead of mongosh) test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"] # With authentication test: ["CMD", "mongosh", "-u", "admin", "-p", "${MONGO_PASSWORD}", "--eval", "db.adminCommand('ping')"]
Pattern 5: Redis
healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 3 start_period: 10s # Redis starts fast
Variations:
# With password test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] # Check specific key exists test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
Pattern 6: MySQL/MariaDB
healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Variations:
# With credentials test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] # Using mysql client test: ["CMD-SHELL", "mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1'"]
Pattern 7: Elasticsearch
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s # ES takes longer to start
Pattern 8: RabbitMQ
healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Pattern 9: Custom Shell Commands
For complex checks using shell scripting:
healthcheck: test: ["CMD-SHELL", "command1 && command2 || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Example (ANyONe Relay):
healthcheck: test: ["CMD-SHELL", "echo 'GETINFO status/circuit-established' | nc -q 1 localhost 9051 | grep -q '250' || exit 1"] interval: 60s timeout: 15s retries: 3 start_period: 120s
Complete Examples
Example 1: Web App with MongoDB (Paaster)
services: paaster: image: wardpearce/paaster:3.1.7 depends_on: mongodb: condition: service_healthy healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 start_period: 30s mongodb: image: mongo:7 healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Example 2: Complex Stack (Paperless-ngx)
services: paperless: image: ghcr.io/paperless-ngx/paperless-ngx:2.13 depends_on: postgres: condition: service_healthy redis: condition: service_healthy gotenberg: condition: service_started # Helper, doesn't need healthy tika: condition: service_started # Helper, doesn't need healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000"] interval: 30s timeout: 10s retries: 3 start_period: 60s # Longer for complex app postgres: image: postgres:16-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-paperless} -d ${POSTGRES_DB:-paperless}"] interval: 30s timeout: 10s retries: 3 start_period: 30s redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 3 start_period: 10s # Redis is fast gotenberg: image: gotenberg/gotenberg:8 # No healthcheck needed - stateless helper tika: image: apache/tika:2.9.1.0 # No healthcheck needed - stateless helper
Example 3: Git Service with PostgreSQL (Forgejo)
services: forgejo: image: codeberg.org/forgejo/forgejo:9 depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"] interval: 30s timeout: 10s retries: 3 start_period: 30s postgres: image: postgres:16-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -U ${FORGEJO_DB_USER:-forgejo} -d ${FORGEJO_DB_NAME:-forgejo}"] interval: 30s timeout: 10s retries: 3 start_period: 30s
Start Period Recommendations
| Service Type | Recommended start_period |
|---|---|
| Redis | 10s |
| Static file server | 10s |
| Simple web app | 30s |
| Node.js app | 30s |
| PostgreSQL | 30s |
| MongoDB | 30s |
| MySQL | 45s |
| Java/Spring Boot | 60-120s |
| Paperless-ngx | 60s |
| Elasticsearch | 60-120s |
| Custom services | Test and adjust |
Dependency Conditions
When to use service_healthy
service_healthydepends_on: database: condition: service_healthy
Use for:
- Databases (PostgreSQL, MongoDB, Redis, MySQL)
- Services that need initialization time
- Services the app actively connects to on startup
When to use service_started
service_starteddepends_on: helper: condition: service_started
Use for:
- Stateless helper services (Gotenberg, Tika)
- Services called on-demand, not at startup
- Fast-starting auxiliary services
Quality Standards
Mandatory Requirements
- All persistent services have health checks
- Databases use appropriate native health commands
- Web services use HTTP health checks
- Dependencies use
conditionservice_healthy - Start period appropriate for service type
Testing Health Checks
# Check health status docker compose ps # View health check logs docker inspect --format='{{json .State.Health}}' container_name
Common Pitfalls
Pitfall 1: Wrong tool for image
Issue: curl not available in Alpine images Solution: Use wget for Alpine, curl for Debian/Ubuntu
Pitfall 2: start_period too short
Issue: Service marked unhealthy during startup Solution: Increase start_period for slow-starting services
Pitfall 3: Checking wrong port
Issue: Health check fails, service works Solution: Use internal container port, not mapped port
Pitfall 4: Missing CMD-SHELL for pipes
Issue: Shell commands fail Solution: Use
["CMD-SHELL", "cmd | grep ..."] for pipes/redirects
Pitfall 5: Health endpoint requires auth
Issue: 401/403 errors in health check Solution: Use unauthenticated health endpoint or add credentials
Integration
Skills-First Approach (v2.0+)
This skill is part of the skills-first architecture - loaded during Generation phase to add health checks after routing configuration.
Related Skills
: Service dependenciesdokploy-compose-structure
: Complex dependency chainsdokploy-multi-service
Invoked By
command: Phase 3 (Generation) - Step 3/dokploy-create
Order in Workflow (Progressive Loading)
: Create base structuredokploy-compose-structure
: Add routing labelsdokploy-traefik-routing- This skill: Add health checks (Step 3)
: Add CF integration (if applicable)dokploy-cloudflare-integration
: Configure environmentdokploy-environment-config
: Create template.tomldokploy-template-toml
See:
.claude/commands/dokploy-create.md for full workflow