Docker healthchecks and restart policies solve a problem a plain docker ps can’t see: a process staying alive doesn’t mean it’s actually serving anything useful. A web server can hang without crashing, and without a HEALTHCHECK, Docker has no way to know.
From starting to healthy or unhealthy
A HEALTHCHECK is defined with –health-cmd on docker run, or with the healthcheck field in a compose.yaml, and it uses four parameters: the interval between checks, the maximum time per attempt, the number of consecutive failures needed to flip to unhealthy, and a start period during which failures don’t count yet. docker inspect –format ‘{{.State.Health.Status}}’ and the STATUS column of docker ps surface that state at any moment.
Restarts: no, on-failure, always, and unless-stopped
The restart policy (–restart) is independent from the healthcheck: it decides what Docker does when the container’s main process exits. on-failure:N only kicks in on a non-zero exit code and accepts a retry cap; always and unless-stopped also restart after a daemon restart, but unless-stopped honors a manual docker stop and won’t bring the container back until you decide to.
service_healthy in Compose
Combining both pieces, depends_on: condition: service_healthy in Compose delays a service’s startup until its dependency’s healthcheck reports healthy, something a plain depends_on, which only orders containers, cannot guarantee. It’s the same idea we covered while building healthchecks and restart policies in Docker Compose, applied here with real commands against a real Docker daemon.
If you’re coming from Docker fundamentals, this lab pairs with what we covered in volumes and bind mounts and Docker networking, and with the rest of our Tools guides. The official reference for the instruction lives in the Docker documentation, the open specification for Compose’s healthcheck field is in the Compose Specification repository, and the command we use to check Redis is documented in the Redis reference.
FAQ
What is a Docker HEALTHCHECK?
It's a command Docker runs inside the container itself at a fixed interval (–health-interval, or the healthcheck field in Compose) to decide whether the process is genuinely serving, not just still running. If the command fails health-retries times in a row, Docker marks the container unhealthy, without restarting it on its own.
What is the difference between the on-failure, always, and unless-stopped restart policies?
on-failure only restarts the container when its main process exits with a non-zero code, and accepts a cap like on-failure:5. always restarts it no matter what, even after a manual docker stop or a daemon restart, unless you remove the container. unless-stopped behaves like always, but it honors an explicit docker stop: it won't bring the container back until you start it yourself or Docker restarts.
How does Compose use depends_on: condition: service_healthy?
With that setting, Compose won't start the dependent service until the healthcheck of the service it depends on reports healthy, not merely once that container exists. Without condition: service_healthy, depends_on only orders container startup, with no guarantee the first one is actually ready to take traffic.