ADR-0004: Container healthchecks — add everywhere, verify-first, skip the un-probeable¶
- Status: Accepted
- Date: 2026-07-14
Context¶
Most containers reported Docker health none because their images define no HEALTHCHECK, so
any container-status view (Arcane, Homarr, docker ps) showed blank health for ~26 of 40
containers. "Running" is not the same as "healthy," and a blank badge is uninformative.
Decision¶
Add a Docker HEALTHCHECK to every container that can support a self-contained probe, under
these rules:
- Verify first. The exact probe must be run inside the container and confirmed to exit 0
before it's written to the compose file. A wrong healthcheck marks a working container
unhealthyand can block anything withdepends_on: condition: service_healthy. - Use whatever the image actually has: an app health subcommand (
/beszel health,diun healthcheck,redis-cli ping),curl/busyboxwgetagainst a real 2xx path,nc -z/python-socket/bash/dev/tcpfor TCP-only or tool-less images. - Recreate per-service, never whole-stack (a whole-stack
up -dcan trip on intentionally- down services like theotbrwith a disconnected radio). Revert any check that goes unhealthy. - Skip, don't fake. Services with no self-contained probe get no healthcheck rather than a misleading one: distroless continuwuity (no shell/tools, no health subcommand) and pure worker sidecars with no port (controller-watch, trmnl-nowplaying).
Consequences¶
- Near-universal green health badges; end state 0 unhealthy across 22 added checks.
- To give a distroless/tool-less service a check later, bake a static probe into a wrapper image or add a sidecar — don't invent a probe that can't run in-container.
- Patterns and the full skip list:
docs/runbooks/monitoring.md.