explainer / Oct 4, 2026

Docker Health Checks Are Not Restart Policies

A failed probe, a stopped process, and an unready dependency need different responses. Understand what Docker and Compose actually automate.

By Stackarr EditorialDocker · Health checks · Homelab reliability · Compose
An open home-server cupboard holds storage hardware, a network switch and a coiled cable beside a portable inspection lamp.
Checking a service and deciding to restart it are separate operational responsibilities.

A Docker health check reports the result of a probe. A restart policy governs what happens when the container stops. On a standalone Docker home server, an unhealthy result does not by itself invoke the container's restart policy. Compose adds dependency readiness rules, but those are not a general-purpose repair controller either. Keeping these responsibilities separate prevents a green dashboard from becoming a false promise of recovery.

This distinction matters for self-hosting because a media server, database, or private cloud application can remain alive while failing the operation a household actually needs. The useful question is not simply whether a container is up. It is what was tested, what failed, and which component has authority to respond.

A health result describes one particular test

Docker's HEALTHCHECK reference defines a probe that executes inside the container. Health begins as starting, becomes healthy after a successful check, and becomes unhealthy after the configured consecutive failures. The health state is additional information alongside the container's lifecycle state.

That location limits what the result proves. A successful internal HTTP request can establish that one endpoint answered from inside the container. It does not establish that the home network can reach the published port, that a reverse proxy forwards correctly, or that a remote viewer can play a particular file. Conversely, a missing probe executable can produce a failed health result even when the application itself works.

Treat the test definition as part of the evidence. A lightweight process check, a database readiness command, and an application transaction answer different questions. None becomes a complete service guarantee merely because Docker displays the same health label.

Recovery after exit follows a different contract

Docker's restart policy documentation describes policies for container exits and daemon restarts. Those events are different from an application probe returning a failure while its main process continues running.

  • no leaves automatic restarting disabled.
  • on-failure responds to a nonzero exit status and can limit retry attempts; it does not restart a container merely because the Docker daemon restarts.
  • always and unless-stopped provide broader restart behavior, with an important distinction around stopped containers and daemon restarts.

A manual stop also has defined policy behavior; it is not equivalent to an unexpected application crash. Do not assume every stopped service should immediately return. During maintenance, remaining stopped may be the intended outcome.

For a stuck process that still exists, changing an exit-based policy does not supply the missing decision to terminate or restart it. That requires application behavior or a separate controller, not a more optimistic interpretation of the health badge.

Dependency readiness is a startup gate

Compose can wait for a dependency's health check before creating a dependent service. Its startup-order documentation distinguishes service_started, service_healthy, and service_completed_successfully. These express whether a dependency must be running, pass its health check, or finish successfully.

This helps when an application starts faster than its database becomes ready. It does not mean that every later database problem automatically restarts the application. Applications still need suitable behavior when established connections fail during normal operation.

There is also a separate restart: true field inside a long-form dependency declaration. Docker documents it in connection with explicit Compose operations that update or restart the dependency. It should not be confused with a service-level restart policy or interpreted as a subscription to every unhealthy event. Identical-looking words at different configuration levels can describe different mechanisms.

A useful probe needs a tolerable failure window

Health checks have intervals, timeouts, retry counts, and startup allowances. These settings trade faster reporting against unnecessary alarms while a service initializes or briefly struggles. The Dockerfile reference explains that checks run relative to completion of earlier checks, so a simple interval-times-retries calculation is not a universal detection deadline.

The startup period is not a promise that all results are ignored until its end. A successful probe during that period establishes startup, after which consecutive failures count. The newer start-interval option also has an Engine compatibility requirement: Docker documents support from version 25.0 onward.

For a homelab, choose what a failure means before shortening the interval. A storage-heavy import and a small stateless service may need different allowances. Testing more often does not make a weak endpoint a better indicator of useful work.

An automatic restart needs an independent safety case

A recovery controller introduces another decision: whether interruption is likely to improve the situation. Restarting cannot create missing disk capacity, correct bad credentials, or establish that a database migration is safe. Repeated interruption can also obscure the original sequence of failures.

A conservative design recommendation is to alert first, then automate only a narrow set of understood failures. Bound retries, preserve diagnostic evidence, and exclude maintenance windows and sensitive stateful operations unless their recovery behavior has been reviewed. These are design recommendations, not capabilities supplied automatically by a Docker health check.

The controller's permissions deserve separate review. Permission to report health is not the same requirement as permission to manage containers. An attractive recovery loop is not sufficient reason to grant broad Docker control without examining its scope.

Read the three signals separately

For ordinary Docker Engine containers managed with Compose, interpret lifecycle, probe status, and dependency readiness as distinct evidence. Swarm services and other orchestrators have different control loops; do not transfer this explanation into those environments without checking their documentation.

A sound home-server reliability plan names the tested operation, the failure signal, and the permitted response. If the container has exited, examine the exit and restart policy. If it is running but unhealthy, examine the probe and application evidence. If a dependent service cannot start, examine the readiness gate. The result is a clearer operational model: detection is useful, but it is not the same thing as recovery.

Verification ledger

Sources and further reading

  1. Dockerfile reference: HEALTHCHECKDocker · Primary source
  2. Start containers automaticallyDocker · Primary source
  3. Control startup and shutdown order in ComposeDocker · Primary source