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_upgradecorrupts data directories). - The Recommended GitOps Strategy:
- Pin container images to specific minor tags or sha256 digests in your Git repository (e.g.
postgres:16.4-alpine, notlatest). - Use an automated dependency bot (such as Renovate) to scan your Git repository and submit pull requests with changelog diffs.
- Merge updates via GitOps (Forgejo + Komodo), allowing pre-merge CI linting and controlled, zero-downtime rolling deployments.
- Pin container images to specific minor tags or sha256 digests in your Git repository (e.g.
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