Docker

Docker Healthchecks vs Orchestrator Probes for Service Readiness

4 min read by DebuggedIt

Quick answer

Quick answer: a Docker HEALTHCHECK reports whether one container is healthy, and Docker Engine, Compose, and Swarm can use that status. Kubernetes ignores it...

Quick answer: a Docker HEALTHCHECK reports whether one container is healthy, and Docker Engine, Compose, and Swarm can use that status. Kubernetes ignores it and relies on its own liveness, readiness, and startup probes. Use readiness to decide whether a service should receive traffic and liveness to decide whether it should be restarted, and keep the two checks deliberately different.

What Does a Docker HEALTHCHECK Actually Do?

The HEALTHCHECK instruction defines a command that Docker runs inside the container at a fixed interval. An exit code of 0 means healthy and 1 means unhealthy, and the result appears as starting, healthy, or unhealthy in the container status. You can tune the interval, the timeout, the retry count, and a start period that gives slow applications time to boot before failures count.

It is just as important to know what it does not do. On plain Docker Engine, an unhealthy status does not restart the container, because restart policies react to process exit only. Compose can use the status through a depends_on condition so a dependent service waits for a healthy database, and Swarm can replace unhealthy tasks. Kubernetes does not read the Dockerfile instruction at all.

Interval choice matters too. A very short interval adds constant load and noise, while a very long one delays detection. For most web services, an interval of 10 to 30 seconds with three retries balances speed and stability, but tune it to how quickly your service needs failures detected.

HEALTHCHECK --interval=30s --timeout=3s --start-period=20s --retries=3 \
  CMD ["/app/api", "healthcheck"]

How Do Liveness, Readiness, and Startup Probes Differ?

Orchestrators separate the questions that a single Docker health status blurs together. Each probe type triggers a different action, which is why mixing them up causes outages:

  • Liveness: asks whether the process is stuck beyond recovery. A failure restarts the container.
  • Readiness: asks whether the instance can serve requests right now. A failure removes it from load balancing without restarting it.
  • Startup: protects slow-starting applications by holding back the other probes until the first success.

Probes can use HTTP requests, TCP connections, commands, or gRPC calls depending on the platform, and the available fields vary by version. Check the official documentation of your orchestrator for exact behavior and defaults.

How Should You Design Health Endpoints?

Keep liveness shallow. If a liveness check queries the database and the database goes down, every instance fails together and the orchestrator restarts your entire fleet, which makes the outage worse and slows recovery. A liveness endpoint should confirm only that the process can respond, for example that its event loop or request handler is not deadlocked.

Readiness can look at critical dependencies, but do it carefully. Use short timeouts, avoid expensive queries, and cache results briefly so probes do not become load. Also decide what should happen when a shared dependency fails: if every instance reports not ready, traffic drops to zero, and serving degraded responses may be better than serving none.

Minimal images often lack curl or wget, so a command-based check fails for the wrong reason. Build a small healthcheck subcommand into your binary, or use HTTP probes from the orchestrator. Keep the check timeout shorter than the interval, and use a start period or startup probe so migrations and cache warmup do not trigger restarts.

Frequently Asked Questions

Does Kubernetes use the Dockerfile HEALTHCHECK?

No. Kubernetes ignores that instruction and uses the probes defined in the pod specification, so you must configure liveness, readiness, and startup probes there.

Will Docker restart an unhealthy container automatically?

Not on plain Docker Engine. The container is only marked unhealthy. Restart policies react to the process exiting, so you need an orchestrator or an external monitor to act on the status.

Should a readiness probe check the database?

It can, if the service cannot work without it, but use timeouts and caching. Weigh whether serving degraded responses is better than removing every instance from rotation.

How do I wait for a healthy dependency in Compose?

Define a healthcheck on the dependency and use the depends_on condition service_healthy in the dependent service. This delays startup until the dependency reports healthy.

Summary

A Docker HEALTHCHECK is a status signal, while orchestrator probes drive real actions like restarts and traffic routing. Keep liveness shallow, make readiness reflect true ability to serve, and give slow starters a start period. Test your health endpoints by deliberately breaking a dependency in staging, and verify probe fields and defaults in the documentation for your platform version.