Difference in docker restart policy between on-failure and unless-stopped?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Docker restart policies look similar at first, but on-failure and unless-stopped solve different operational problems. The core distinction is simple: on-failure reacts to error exits, while unless-stopped is about keeping a service running unless a human explicitly stops it.
What on-failure Means
The on-failure policy restarts a container only when the container process exits with a non-zero status code. If the process exits successfully with code 0, Docker does not restart it.
Example:
You can also limit the number of retries:
This is a good fit for batch-like workloads or service processes that may fail transiently and should get a few automatic retries.
What unless-stopped Means
The unless-stopped policy tells Docker to restart the container whenever it stops, regardless of exit status, unless the container was explicitly stopped by the user.
Example:
This is typically what you want for long-running services such as web apps, background workers, and reverse proxies that should come back after Docker daemon restarts or host reboots.
The Real Behavioral Difference
The easiest way to think about it is this:
- '
on-failurecares about whether the process failed' - '
unless-stoppedcares about whether the service should keep running'
If a container exits normally:
- '
on-failureleaves it stopped' - '
unless-stoppedstarts it again'
If a container crashes with a non-zero exit code:
- '
on-failurerestarts it' - '
unless-stoppedalso restarts it'
If you manually stop the container with docker stop:
- '
on-failureleaves it stopped because that is not a crash condition' - '
unless-stoppedalso leaves it stopped because the stop was intentional'
The difference becomes most visible when the container exits cleanly or when the host restarts and you expect the container to come back as a persistent service.
Choosing Between Them
Use on-failure when the container is more like a job than a daemon. Examples include:
- one-off data processing
- migration jobs
- short-lived workers that should retry on crash
- scripts that are expected to finish when successful
Use unless-stopped when the container represents a service that should generally stay up forever. Examples include:
- web servers
- monitoring agents
- queue consumers
- local development infrastructure you want to survive reboots
Compose Example
In Docker Compose, the same idea appears under the restart field:
Here the API is treated as a persistent service, while the importer is treated as a retryable job.
Operational Tradeoffs
unless-stopped is convenient, but it can hide problems if a container is repeatedly failing on startup. The service keeps trying to come back, which may look resilient but can create noisy restart loops.
on-failure is more conservative. It is often better when success should mean completion and staying stopped is the correct final state.
The right policy depends on whether the container is supposed to finish or supposed to stay alive.
Common Pitfalls
The biggest mistake is using on-failure for a long-running service that sometimes exits cleanly. If the process exits with code 0, Docker will not restart it.
Another mistake is using unless-stopped for short-lived jobs. A successful run may immediately trigger another restart, which is not what you wanted.
Teams also confuse restart policies with application health checks. Restart policy reacts to process exit, not to every unhealthy runtime condition.
Finally, do not assume restart policy replaces proper observability. A container that restarts automatically can still be broken.
Summary
- '
on-failurerestarts only when the container exits with a non-zero code.' - '
unless-stoppedkeeps restarting the container unless a user explicitly stops it.' - Use
on-failurefor jobs and retryable crash scenarios. - Use
unless-stoppedfor services that should stay running. - Choose based on whether the container is meant to complete or to persist.

