By default, a crashed or stopped container simply stays stopped. Restart policies and healthchecks let Docker automatically recover failed containers and detect when an application is unhealthy even if the process technically hasn't exited.
Restart Policies
Set with --restart on the command line, or restart: in Compose.
| Policy | Behavior |
|---|---|
no | Never restart automatically (default) |
on-failure | Restart only if the container exits with a non-zero (error) code |
unless-stopped | Always restart unless manually stopped; recommended for most production services |
always | Always restart, even after a manual stop, if the daemon itself restarts |
Setting a Restart Policy
docker run -d --restart unless-stopped nginx
In Compose:
services:
web:
image: nginx
restart: unless-stopped
Limiting Restart Attempts
docker run -d --restart on-failure:5 myapp
This gives up after 5 failed restart attempts, preventing an infinite crash loop from consuming resources.
Why Restart Policies Alone Aren't Enough
A container process can technically stay running while the application inside it is unresponsive (e.g. a web server accepting connections but timing out on every request). Docker's restart policy won't catch this — that's what healthchecks solve.
Adding a Healthcheck in Compose
services:
web:
image: myapp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
start_period gives the app time to boot before failed checks start counting against it.
Adding a Healthcheck in a Dockerfile
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Checking Container Health Status
docker ps
The STATUS column will show (healthy), (unhealthy), or (starting).
For detailed healthcheck history:
docker inspect --format='{{json .State.Health}}' CONTAINER_NAME
Using Health Status with depends_on
Ensure a dependent service only starts after the database is actually ready, not just running:
services:
web:
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
retries: 5
Common Errors
Container marked unhealthy despite working correctly — the healthcheck command may need adjusting (wrong port, endpoint, or tool not installed inside the container's image).
Infinite restart loop — use on-failure:N to cap attempts, and check docker logs for the underlying crash cause instead of relying solely on auto-restart.
Best Practices
- Use
unless-stoppedfor essentially all production services - Add healthchecks to any service another container depends on
- Set a reasonable
start_periodfor apps with slow startup
FAQ
What happens if the Docker daemon restarts?
Containers with always or unless-stopped (and not manually stopped beforehand) will automatically restart when the daemon comes back up, including after a full VPS reboot if Docker itself is enabled at boot.
Related Articles
- Deploy Your First Docker Container
- Docker Compose Troubleshooting: Common Errors & Fixes
- Run MySQL/PostgreSQL/Redis in Docker Containers
