# Docker Healthchecks

## Why Healthchecks Matter
- Without a healthcheck, Docker only knows if a process is running — not if it's actually working
- `depends_on` with `condition: service_healthy` ensures dependent services wait for readiness
- Healthchecks enable automatic restarts of unhealthy containers with `restart: unless-stopped`

## HTTP Healthcheck
For web applications and APIs:
```yaml
healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 30s
```
Alternative using `curl`:
```yaml
healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
```
Note: `curl` is not available in all images (Alpine doesn't include it). Prefer `wget` for Alpine-based images.

## TCP Healthcheck
For services that listen on a port but don't have HTTP:
```yaml
healthcheck:
  test: ["CMD-SHELL", "nc -z localhost 5432 || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 20s
```

## Database-Specific Healthchecks
- **PostgreSQL**: `pg_isready -U postgres`
- **MySQL**: `mysqladmin ping -h localhost`
- **Redis**: `redis-cli ping`
- **MongoDB**: `mongosh --eval "db.adminCommand('ping')"`
- **Elasticsearch**: `curl -f http://localhost:9200/_cluster/health || exit 1`

## Parameters Explained
| Parameter | Purpose | Guideline |
|-----------|---------|-----------|
| `interval` | Time between checks | 10–30s for most services |
| `timeout`  | Max time for a single check | 3–10s |
| `retries`  | Failures before marking unhealthy | 3–5 |
| `start_period` | Grace period on container start | Match the app's typical startup time (10–60s) |

## Using with depends_on
```yaml
services:
  app:
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
```

## Common Gotchas
- **Missing tools**: Alpine images don't have `curl` — use `wget --spider` or install `curl` in your Dockerfile
- **Wrong port**: The healthcheck runs INSIDE the container — use the container's internal port, not the mapped host port
- **Too-short start_period**: Apps that need database migrations or heavy initialization may fail healthchecks during startup. Set `start_period` generously
- **Healthcheck overhead**: Don't set `interval` too low on resource-constrained devices (Raspberry Pi). 30s is fine for most cases
