·9 min read

Docker Health Checks: Building Self-Healing Containers

Implement effective health checks in Docker and Podman containers. Learn start_period, interval, timeout, retries, and integration with orchestration tools.

DockerPodmanHealth ChecksDevOpsReliability

Docker health checks let containers report their status automatically. When a container becomes unhealthy, Docker can restart it, notify monitoring systems, or remove it from load balancers.

Why Health Checks Matter

Without health checks:

  • Container running but app crashed
  • Database accepting connections but can't execute queries
  • Web server up but returning 500 errors
  • Manual intervention required

With health checks:

  • Automatic failure detection
  • Self-healing (auto-restart)
  • Load balancer integration
  • Monitoring alerts

Basic Health Check

Simple HTTP Check

# Dockerfile
FROM nginx:latest

# Add health check
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

Or in compose:

# docker-compose.yml
services:
  web:
    image: nginx
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Health Check Fields

  • test — Command to run (exit 0 = healthy, 1 = unhealthy)
  • interval — Time between checks (default: 30s)
  • timeout — Max time for check (default: 30s)
  • retries — Failed checks before unhealthy (default: 3)
  • start_period — Grace period for startup (default: 0s)

Common Health Check Patterns

Pattern 1: HTTP Endpoint

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 30s
  timeout: 10s
  retries: 3

Application should return 200 OK when healthy:

// Node.js example
app.get('/health', (req, res) => {
  // Check dependencies
  if (db.connected && cache.connected) {
    res.status(200).json({ status: 'healthy' });
  } else {
    res.status(503).json({ status: 'unhealthy' });
  }
});

Pattern 2: Database Connection

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres"]
  interval: 10s
  timeout: 5s
  retries: 5

Pattern 3: Process Check

healthcheck:
  test: ["CMD-SHELL", "pidof nginx || exit 1"]
  interval: 30s
  timeout: 5s
  retries: 3

Pattern 4: Custom Script

healthcheck:
  test: ["CMD", "/app/healthcheck.sh"]
  interval: 30s
  timeout: 10s
  retries: 3
#!/bin/bash
# /app/healthcheck.sh

# Check database
if ! pg_isready -h db -U postgres; then
  echo "Database not ready"
  exit 1
fi

# Check cache
if ! redis-cli -h cache ping | grep -q PONG; then
  echo "Cache not ready"
  exit 1
fi

# Check disk space
if [ $(df /data | tail -1 | awk '{print $5}' | sed 's/%//') -gt 90 ]; then
  echo "Disk space low"
  exit 1
fi

echo "All checks passed"
exit 0

Advanced Health Checks

Multi-Stage Health Check

healthcheck:
  test: |
    bash -c '
      # Check if process is running
      pidof node || exit 1
      
      # Check HTTP endpoint
      curl -f http://localhost:3000/health || exit 1
      
      # Check database connection
      node -e "require('./db').check().then(() => process.exit(0)).catch(() => process.exit(1))"
    '
  interval: 30s
  timeout: 15s
  retries: 3

Gradual Health Check

healthcheck:
  test: |
    bash -c '
      # First 5 minutes: just check process
      if [ $$(ps -p 1 -o etimes=) -lt 300 ]; then
        pidof node || exit 1
      else
        # After 5 minutes: full health check
        curl -f http://localhost:3000/health || exit 1
      fi
    '
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 60s

Using Health Checks

View Health Status

# Check container health
docker ps
# Shows (healthy), (unhealthy), or (health: starting)

# Detailed health info
docker inspect --format='{{.State.Health.Status}}' container_name

# View health check logs
docker inspect --format='{{json .State.Health}}' container_name | jq

Auto-Restart Unhealthy Containers

services:
  web:
    image: myapp
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      retries: 3
    restart: on-failure

Load Balancer Integration

Nginx upstream with health checks:

upstream backend {
    server backend1:8080;
    server backend2:8080;
    
    # Requires nginx plus
    health_check interval=5s fails=3 passes=2;
}

HAProxy with health checks:

backend app
    balance roundrobin
    option httpchk GET /health
    server app1 app1:8080 check inter 5s fall 3 rise 2
    server app2 app2:8080 check inter 5s fall 3 rise 2

Docker Compose with Health Checks

Complete Example

version: '3.8'

services:
  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - pgdata:/var/lib/postgresql/data

  cache:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped
    ports:
      - "80:3000"

volumes:
  pgdata:

The depends_on with condition: service_healthy ensures web starts only after db and cache are healthy.

Monitoring Health Checks

Prometheus Metrics

services:
  web:
    image: myapp
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
    labels:
      - "prometheus-job=myapp"

Alerting

# docker-compose.yml
services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
    restart: on-failure
    logging:
      driver: syslog
      options:
        syslog-address: "tcp://logs.example.com:514"

FoxTerm Health Check Support

FoxTerm makes health checks visual and manageable:

Health Dashboard

  • Real-time health status for all containers
  • Health check history and trends
  • Failure notifications
  • Quick restart actions

Health Check Editor

  • Visual health check configuration
  • Test health checks before deploying
  • Template library for common patterns
  • Validation and best practices

Integration

  • Auto-detect health check status
  • Alert on unhealthy containers
  • One-click restart
  • Health check logs viewer

Best Practices

  1. Implement health endpoints — /health should check all dependencies
  2. Set appropriate intervals — Don't check too frequently (overhead) or too slowly (delayed detection)
  3. Use start_period — Give apps time to initialize
  4. Check dependencies — Health check should verify database, cache, etc.
  5. Log health check results — Debug failures easily
  6. Test health checks — Verify they work before production
  7. Monitor trends — Track health check failures over time

Conclusion

Docker health checks enable self-healing containers that detect and recover from failures automatically. Combined with proper restart policies and monitoring, they significantly improve application reliability.

FoxTerm makes health checks visual and manageable, with real-time status and one-click actions.


FoxTerm Pro includes health check monitoring and management. Download at foxterm.app.