Back to skills
extension
Category: Development & EngineeringNo API key required

dokploy-health-patterns

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

personAuthor: jakexiaohubgithub

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:

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

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

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

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

# 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