Zero-Downtime Container Healthchecks, Auto-Healing & Safe Update Strategies

3 min read

A running Docker container is not necessarily a working container. Standard container runtimes only monitor PID 1: if your web application or database deadlocks, encounters an out-of-memory lock, or loses its upstream database connection, the container remains reported as Up (healthy) even though all user requests are failing. Robust homelab infrastructure requires explicit, declarative healthchecks in every Compose stack, paired with automated recovery daemons like autoheal and a disciplined, non-destructive container update strategy.

⚡ Quick Runbook: Production Healthchecks & Autoheal

Deploy the automated recovery daemon and sample production healthcheck configurations:

# /opt/stacks/autoheal/compose.yaml
services:
  autoheal:
    image: willfarrell/autoheal:latest
    container_name: autoheal
    restart: unless-stopped
    environment:
      - AUTOHEAL_CONTAINER_LABEL=all
      - AUTOHEAL_INTERVAL=15
      - AUTOHEAL_START_PERIOD=60
      - AUTOHEAL_DEFAULT_STOP_TIMEOUT=10
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  # Production service example with robust healthcheck
  web-app:
    image: nginx:alpine
    container_name: web-app
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
    labels:
      - "autoheal=true"

Production Healthcheck Templates by Workload

Implement the appropriate native health probe based on service architecture:

1. PostgreSQL Databases

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
  interval: 15s
  timeout: 5s
  retries: 5
  start_period: 30s

2. Redis In-Memory Cache

healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 10s
  timeout: 3s
  retries: 3
  start_period: 10s

3. Node.js / Python API Microservices

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3000/healthz"]
  interval: 20s
  timeout: 5s
  retries: 3
  start_period: 40s

Container Image Update Strategies: Renovate vs Watchtower

Automated image updating requires careful architectural separation between stateless application containers and stateful database engines:

  • The Watchtower Anti-Pattern: Running unpinned, unmonitored Watchtower instances across all containers frequently leads to broken databases (e.g., auto-upgrading PostgreSQL from v15 to v16 without running pg_upgrade corrupts data directories).
  • The Recommended GitOps Strategy:
    1. Pin container images to specific minor tags or sha256 digests in your Git repository (e.g. postgres:16.4-alpine, not latest).
    2. Use an automated dependency bot (such as Renovate) to scan your Git repository and submit pull requests with changelog diffs.
    3. Merge updates via GitOps (Forgejo + Komodo), allowing pre-merge CI linting and controlled, zero-downtime rolling deployments.

Verification & Fault Injection Testing

Test that autoheal detects and recycles deadlocked containers as expected:

# Monitor container health status
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.State}}"

# Simulate service failure by stopping the internal web server without killing the container
docker exec -it web-app nginx -s stop

# Observe autoheal logs reacting to the unhealthy status and triggering a restart
docker logs -f autoheal

Related Runbooks in This Series

Tags:

← Previous:
Next: →