Why Health Checks Matter
A container process can be running while the application inside it is deadlocked, unresponsive, or unable to serve traffic. Docker's default process-based health monitoring only knows if the main process has exited, not whether the application is actually functional. HEALTHCHECK instructions let Docker actively probe application health and mark containers accordingly.
Cricket analogy: A batsman standing at the crease looks like he's still playing, but he could be concussed and unable to react to the next ball; the umpire's default check of 'is he on the field' doesn't catch this, just as Docker's process check misses an unresponsive app.
Defining a HEALTHCHECK in a Dockerfile
The HEALTHCHECK instruction defines a command Docker runs periodically inside the container. Based on the command's exit code, Docker reports the container as healthy, unhealthy, or starting.
Cricket analogy: A team doctor periodically runs a specific reflex test on a player during a match to check if they're actually fit, not just present on the field; based on the test's pass or fail result, the player is cleared, benched, or monitored, mirroring HEALTHCHECK's exit codes.
FROM nginx:1.27-alpine
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost/health || exit 1Key options: '--interval' sets time between checks, '--timeout' is how long a check may run before being considered failed, '--start-period' gives the app time to boot before failures count toward the retry threshold, and '--retries' is the number of consecutive failures needed to mark the container unhealthy.
Cricket analogy: A fitness test schedule during a tour sets how often players are checked (--interval), how long each test may take before it's abandoned (--timeout), a grace period after a long flight before results count against them (--start-period), and how many failed tests before being ruled out (--retries).
Checking Health Status
Once a HEALTHCHECK is defined, 'docker ps' shows the health state next to the container status, and 'docker inspect' exposes the full health check log including recent exit codes and output.
Cricket analogy: The scoreboard shows a player's current fitness status (fit, injured, under assessment) at a glance, while the team doctor's full medical log records every past test result and reading, mirroring how 'docker ps' shows health state while 'docker inspect' exposes the full log.
docker ps
# STATUS column shows: Up 2 minutes (healthy)
docker inspect --format='{{json .State.Health}}' mycontainerRestart Policies
Restart policies tell the Docker daemon what to do when a container's main process exits. They are set with '--restart' on 'docker run' or the 'restart' key in Docker Compose, and they operate independently of HEALTHCHECK — Docker does not automatically restart a container just because it becomes unhealthy; only orchestrators like Kubernetes or Swarm act on health status to reschedule.
Cricket analogy: A team's policy on whether an injured bowler is automatically sent back in for the next over is separate from the doctor's fitness assessment; the coach decides restart policy, but only the team management (like an orchestrator) actually benches a player for poor form.
# Never restart automatically (default)
docker run --restart no myapp
# Always restart, including after daemon restart
docker run --restart always myapp
# Restart unless the container was explicitly stopped
docker run --restart unless-stopped myapp
# Restart only on non-zero exit, up to 5 times
docker run --restart on-failure:5 myapp'unless-stopped' is generally preferred over 'always' for long-running services because it respects an operator's explicit 'docker stop', while 'always' will restart the container even after a manual stop if the Docker daemon itself restarts.
Combining Health Checks with Compose
In Docker Compose, you can define both healthcheck and restart, and use 'depends_on' with a 'condition: service_healthy' so dependent services only start once a service reports healthy, avoiding race conditions on startup.
Cricket analogy: A tour schedule can require that the reserve wicketkeeper only takes the field once the main keeper has passed the team doctor's fitness check, avoiding the chaos of a keeper walking out mid-injury; this mirrors 'depends_on' with 'condition: service_healthy'.
services:
api:
image: myapp:1.4.0
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
worker:
image: myworker:1.0.0
depends_on:
api:
condition: service_healthyA container marked 'unhealthy' by plain Docker (not Swarm/Kubernetes) will keep running unless you build separate automation to react to it — HEALTHCHECK alone does not trigger a restart.
- HEALTHCHECK actively probes application health, not just process liveness
- start-period gives the app a grace window before failures count against retries
- Restart policies (no, always, unless-stopped, on-failure) control automatic container restarts on the Docker daemon
- Plain Docker does not restart a container just because it's marked unhealthy
- Compose's depends_on with condition: service_healthy sequences startup correctly
- 'unless-stopped' respects explicit manual stops, unlike 'always'
Practice what you learned
1. What does the --start-period option in a HEALTHCHECK instruction control?
2. Which restart policy respects an operator's explicit 'docker stop' command, unlike 'always'?
3. In plain Docker (no orchestrator), what happens when a container's HEALTHCHECK reports 'unhealthy'?
4. In Docker Compose, what does 'depends_on: condition: service_healthy' achieve?
5. Which restart policy allows a limited number of automatic restarts only on non-zero exit codes?
Was this page helpful?
You May Also Like
Docker Compose Basics
Learn how Docker Compose defines and runs multi-container applications from a single YAML file, replacing long manual docker run commands.
Running and Managing Containers
Learn the core Docker CLI commands to start, inspect, stop, and remove containers, plus how to view logs and execute commands inside a running container.
Rolling Updates and Rollbacks
Learn how Kubernetes Deployments update Pods gradually with zero downtime and how to roll back safely when a release breaks.
Kubernetes Monitoring and Logging
Learn the core tools and patterns for observing cluster and application health: metrics, logs, and the Prometheus/Grafana stack.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsCI/CD Tools & Pipelines Study Notes
YAML · 37 topics