sehaj/learn
Docker/03 Running containers

03.05 · with code · 9 min

Restart policies

Tell Docker what to do when a container's process dies: nothing, retry a few times, or keep it up forever.

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

PolicyRestarts when…
no (default)never
on-failure[:N]it exits with a non-zero code, up to N times if you give a number
alwaysit exits for any reason, and when the Docker daemon starts
unless-stoppedlike 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:

❯terminal
$ 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}}' flaky
status=exited exit=1 restarts=3
$ docker logs flaky
starting
starting
starting
starting

One run plus three restarts: four lines of output.

always restarts even after a clean exit, but respects a manual stop:

❯terminal
$ docker run -d --name always1 --restart always alpine sh -c 'sleep 1; exit 0'
$ docker inspect -f 'status={{.State.Status}} restarts={{.RestartCount}}' always1
status=running restarts=4
$ docker stop always1
$ docker inspect -f 'status={{.State.Status}} restarts={{.RestartCount}}' always1
status=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:

❯terminal
$ 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.

Predict first

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?

Commit to an answer before you read on.

Changing a running container's policy

You don't need to recreate a container to change its policy:

update
docker update --restart unless-stopped notes
CheckpointCrash it on purpose

Run 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

JuniorfreqGood to knowConcept

What's the difference between the always and unless-stopped restart policies?

MidfreqMust-knowDebugging

A container is stuck in 'Restarting'. Walk through how you'd debug it.

Report a mistakeEdit this page