A restart policy is one line, and it decides whether your container comes back on its own after a crash, a reboot, or a manual stop. Get it right and your services survive a server restart without you touching them. Get it wrong and you either lose a service after every reboot or fight a container that refuses to stay down.
Docker has four restart policies: no, always, unless-stopped, and on-failure. They sound self-explanatory, but the differences between always and unless-stopped — and how each one reacts when the Docker daemon itself restarts — are where people get caught.
This guide explains exactly what each policy does in three situations that matter: the process crashes, the host reboots, and you stop the container by hand.
The four policies at a glance
# Set on docker run
docker run -d --restart=unless-stopped --name web nginx:1.27
# Or in a Compose file
# restart: unless-stopped
Here’s how each policy behaves in the three scenarios that actually come up:
What each policy does in three situations
| Policy | Process crashes |
|---|---|
| no (default) | Stays stopped |
| on-failure | Restarts (if exit ≠ 0) |
| always | Restarts |
| unless-stopped | Restarts |
Read the bottom two rows carefully — that one column on the right is the whole difference between always and unless-stopped.
no — the default that does nothing
no is the default policy. If you don’t pass --restart, this is what you get. The container runs until the process exits or you stop it, and then it stays stopped. No automatic recovery from anything.
docker run -d --name once alpine sleep 30
# After 30 seconds the process exits and the container stays stopped.
This is the right choice for one-off tasks, short scripts, and anything you run interactively and don’t want resurrected. It’s the wrong choice for a web server or database you expect to keep running, because a single crash or a reboot takes it down for good.
on-failure — retry only when something broke
on-failure restarts the container only when it exits with a non-zero exit code, which is how a process signals an error. A clean exit (code 0) is treated as success and the container stays stopped.
docker run -d --restart=on-failure:5 --name worker my-batch-job
That :5 is a retry cap. Docker will restart the container up to five times; after the fifth failure it gives up and leaves it stopped. Without the cap, a job that fails instantly on every start would loop forever, which is rarely what you want for a batch process.
on-failure fits jobs and workers: a task that should retry a few times if it errors, but shouldn’t restart endlessly and shouldn’t relaunch after finishing normally. It’s a poor fit for a service that exits 0 on a crash or one you always want running regardless of exit code.
always — bring it back no matter what
always restarts the container whenever it stops, with one important twist around manual stops.
If the process crashes, it restarts. If the host or the Docker daemon restarts, the container starts again. And if you stop it yourself with docker stop, it stays stopped for now — but the next time the Docker daemon starts, it comes back anyway.
docker run -d --restart=always --name proxy nginx:1.27
That last part is the gotcha. You stop a container on purpose, reboot the box for maintenance, and the container you deliberately stopped is suddenly running again. always doesn’t remember that you wanted it down — it only knows it should be running whenever the daemon is up.
Use always when you genuinely want a container running at all times and a manual stop should only ever be temporary. For most services, that’s stronger than you want, which is why the next policy usually wins.
unless-stopped — the sensible default
unless-stopped behaves like always in every case except one: it remembers a manual stop. If you stop the container yourself, it stays stopped — across daemon restarts and host reboots — until you start it again.
docker run -d --restart=unless-stopped --name web nginx:1.27
Walk through the scenarios:
- Process crashes → Docker restarts it.
- Host reboots while the container was running → it starts back up.
- You run
docker stop web→ it stays down, and a reboot won’t bring it back. - You run
docker start webagain → it’s back under the policy.
That behavior matches how people actually think. “Keep this running, but if I stop it, I meant it.” For nearly every long-running service — web servers, databases, reverse proxies — this is the policy to reach for.
Setting and changing policies
In a Compose file, the policy is a single line per service:
services:
web:
image: nginx:1.27
restart: unless-stopped
worker:
image: my-batch-job
restart: on-failure
Note that Compose uses restart: without the -- prefix, and on-failure with a retry cap isn’t expressed here the same way as on the CLI — for capped retries in Compose, use the long-form deploy.restart_policy. For the simple cases above, the short form is all you need.
To change the policy on a container that’s already running, you don’t have to recreate it:
# Change policy in place on a running container
docker update --restart=unless-stopped web
# Confirm what policy a container currently has
docker inspect -f '{{ .HostConfig.RestartPolicy.Name }}' web
Choosing a restart policy
- Long-running service you sometimes stop for maintenance → unless-stopped
- Container that must always run, even after a manual stop → always
- Batch job or worker that should retry on error → on-failure (add a retry cap)
- One-off task or interactive run you don't want resurrected → no
- Confirm the policy with docker inspect after setting it
When the policy isn’t the problem
A restart policy does exactly what it’s told, which is why a container stuck in a restart loop is usually not a policy bug. With always or unless-stopped, a container that crashes the instant it starts will be relaunched again and again — the policy keeps doing its job while the container keeps failing.
When that happens, don’t change the policy first. Read the logs and find out why the container exits:
docker logs --tail 50 web
docker compose logs --tail 50 web
The real cause is almost always a bad config value, a missing mounted file, a port conflict, or a dependency that isn’t ready. Fix that and the loop stops. There’s a full diagnostic walkthrough in fixing a container that keeps restarting, and if the daemon itself isn’t reachable, start with fixing cannot connect to the Docker daemon.
For most stacks, set unless-stopped on your services and move on. It survives the reboots and crashes you care about, respects the stops you make on purpose, and stays out of your way the rest of the time.