The core idea
By default, when a container's main process exits, the container just stays exited. A restart policy tells the Docker daemon to start it again, depending on how it exited and whether you stopped it on purpose. It's the simplest form of self-healing, and on a single server it's often all you need.
The four policies
| Policy | Restarts when… |
|---|---|
no (default) | never |
on-failure[:N] | it exits with a non-zero code, up to N times if you give a number |
always | it exits for any reason, and when the Docker daemon starts |
unless-stopped | like always, except a container you stopped stays stopped across daemon restarts |
docker stop never triggers a restart: a manual stop always wins until the next daemon restart. The difference
between always and unless-stopped only shows up then: after a reboot, always brings back containers you'd
stopped, and unless-stopped leaves them alone.
See them work
on-failure:3 retries a failing container three times, then gives up:
$ docker run -d --name flaky --restart on-failure:3 alpine sh -c 'echo starting; exit 1'$ docker inspect -f 'status={{.State.Status}} exit={{.State.ExitCode}} restarts={{.RestartCount}}' flakystatus=exited exit=1 restarts=3$ docker logs flakystartingstartingstartingstarting
One run plus three restarts: four lines of output.
always restarts even after a clean exit, but respects a manual stop:
$ docker run -d --name always1 --restart always alpine sh -c 'sleep 1; exit 0'$ docker inspect -f 'status={{.State.Status}} restarts={{.RestartCount}}' always1status=running restarts=4$ docker stop always1$ docker inspect -f 'status={{.State.Status}} restarts={{.RestartCount}}' always1status=exited restarts=4
Crash loops and backoff
A container that dies instantly under always doesn't restart in a tight loop. Docker waits between attempts,
doubling the delay each time (starting at 100 ms), and resets it once the container has stayed up for a while:
$ docker run -d --name crashy --restart always alpine sh -c 'exit 1'$ docker ps -a --filter name=crashy --format '{{.Status}}'Restarting (1) 4 seconds ago
Restarting (1) means "exited with code 1, waiting to try again". If you see it, read docker logs: the reason is
almost always in the last few lines.
A web API should come back after a crash and after the server reboots, but stay down if an engineer stops it to investigate. Which policy?
Changing a running container's policy
You don't need to recreate a container to change its policy:
docker update --restart unless-stopped notesRun the notes API with --restart on-failure:5 -e MAX_NOTE_LENGTH=0. The invalid config makes it exit with 1 on every start. Watch docker ps -a show it restarting, then check RestartCount settle at 5. Then run it properly with unless-stopped, restart Docker Desktop (or the daemon), and check it came back.
STUCK? ▸
No restarts with on-failure: the app exited with 0. Use always or make sure the failure exits non-zero, as the notes API's config check does.
Recap
Interview questions
What's the difference between the always and unless-stopped restart policies?
A container is stuck in 'Restarting'. Walk through how you'd debug it.