Agent skill

dokploy-health-patterns

Health check patterns for different service types in Dokploy templates. Covers HTTP, PostgreSQL, MongoDB, Redis, MySQL, and custom health checks.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/dokploy-health-patterns

SKILL.md

Dokploy 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 service_started instead)

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:

yaml
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
interval 30s Increase for resource-constrained systems
timeout 10s Increase for slow-starting services
retries 3 Increase for flaky services
start_period 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):

yaml
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:${PORT}/"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Variations:

yaml
# 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:

yaml
healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:${PORT}"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Example (Paaster):

yaml
healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Pattern 3: PostgreSQL

yaml
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Variations:

yaml
# 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

yaml
healthcheck:
  test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Variations:

yaml
# 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

yaml
healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 10s  # Redis starts fast

Variations:

yaml
# 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

yaml
healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Variations:

yaml
# 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

yaml
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

yaml
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:

yaml
healthcheck:
  test: ["CMD-SHELL", "command1 && command2 || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Example (ANyONe Relay):

yaml
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)

yaml
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)

yaml
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)

yaml
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

yaml
depends_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

yaml
depends_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 service_healthy condition
  • Start period appropriate for service type

Testing Health Checks

bash
# 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

  • dokploy-compose-structure: Service dependencies
  • dokploy-multi-service: Complex dependency chains

Invoked By

  • /dokploy-create command: Phase 3 (Generation) - Step 3

Order in Workflow (Progressive Loading)

  1. dokploy-compose-structure: Create base structure
  2. dokploy-traefik-routing: Add routing labels
  3. This skill: Add health checks (Step 3)
  4. dokploy-cloudflare-integration: Add CF integration (if applicable)
  5. dokploy-environment-config: Configure environment
  6. dokploy-template-toml: Create template.toml

See: .claude/commands/dokploy-create.md for full workflow

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results