skip to content

Docker Engine supports four container restart policies — `no`, `on-failure`, `always` and `unless-stopped`. What does each one mean, and how do you set or change the policy on a container?

level: juniorimportance: must knowfreq 62%

answer

  1. no / on-failure[:N] / always / unless-stopped
  2. default is `no`
  3. on-failure = non-zero exit only
  4. unless-stopped survives reboot as stopped
  5. --restart and --rm are mutually exclusive

basics

~20 s

no never restarts (the default). on-failure[:N] restarts only on a non-zero exit, at most N times. always restarts on any exit and after daemon start. unless-stopped is like always but stays down once you stopped it. Set with --restart; change with docker update --restart.

solid answer

~50 s

A restart policy tells the Docker daemon what to do when a container's main process exits. Four values: - **`no`** (default) — never restart automatically. - **`on-failure[:max-retries]`** — restart only when the exit code is non-zero; the optional number caps the attempts. - **`always`** — restart whenever the container stops, whatever the exit code, and start it again when the daemon starts. If you `docker stop` it, it stays down *until the daemon restarts*, then it comes back. - **`unless-stopped`** — same as `always`, except a container you explicitly stopped stays stopped across daemon restarts and host reboots. Set it at creation: `docker run --restart=unless-stopped …`; in Compose it's the `restart:` key. Change it on an existing container with `docker update --restart=on-failure:3 <id>`. `--restart` cannot be combined with `--rm`. The daemon only honours the policy once the container has actually started successfully, and it backs off exponentially between attempts.

code

bash · 7 lines
bash
docker run -d --name web --restart=unless-stopped nginx:alpine

docker run -d --name job --restart=on-failure:3 my/batch:1.0

docker inspect -f '{{.HostConfig.RestartPolicy.Name}} {{.RestartCount}}' web

docker update --restart=no web

go deeper

for a junior

Name the four values, state that no is the default, and know --restart on docker run plus the Compose restart: key.

for a middle

Add the exit-code rule for on-failure, the docker update --restart path, and that policies react to process exit only — not to health checks.

for a senior

Frame it as choosing a supervision owner: unless-stopped for host services, on-failure:N for retryable jobs, no under an orchestrator, and mention the exponential backoff guard rail.

for a principal

Treat restart policy as one layer in a supervision stack and argue for exactly one owner of restarts per workload, with the policy expressed in the same declarative artifact as the rest of the deployment.

## What a restart policy is A Docker container wraps one main process (PID 1 inside the container). When that process exits, the container enters the `exited` state and, by default, simply stays there. A **restart policy** is a per-container instruction to the Docker daemon (`dockerd`): *when this container's main process exits, should you start it again?* It is the daemon's built-in supervision, comparable to what `systemd`'s `Restart=` does for a host service. The policy is stored in the container's configuration (`HostConfig.RestartPolicy`), so it survives daemon restarts and host reboots, and you can read it back with `docker inspect`. ## The four policies **`no`** — the default. Nothing is restarted automatically. Use it for one-shot jobs, batch tasks, and anything supervised from outside (a systemd unit, an orchestrator, a CI runner). **`on-failure[:max-retries]`** — restart *only* if the container exited with a non-zero status. Exit code 0 means "the job finished", so the container is left stopped. The optional `:N` caps the number of consecutive restart attempts; without it, retries are unlimited. This is the right policy for batch work that should be retried but must be allowed to succeed and stay finished. **`always`** — restart the container every time it stops, regardless of exit code, and start it again whenever the daemon starts. The subtlety: if you run `docker stop`, the daemon records that the stop was deliberate and does not immediately restart it — but that memory does not survive a daemon restart, so after a `dockerd` restart or host reboot the container comes back up. **`unless-stopped`** — identical to `always` except for that last point: a container you explicitly stopped remains stopped even after the daemon restarts. This is usually the policy people actually want for long-running services on a single host, because "I took it down on purpose" survives a reboot. ## Setting and changing it At creation time: `docker run -d --restart=unless-stopped nginx`. In Compose, the `restart:` key on a service takes the same four values (`restart: on-failure:3`). On an existing container, `docker update --restart=<policy> <container>` changes the policy in place without recreating it — useful when you started something with the default `no` and want it supervised. Two constraints worth remembering: `--restart` is mutually exclusive with `--rm` (Docker refuses the combination, since auto-removal and auto-restart contradict each other), and in Swarm mode a *service*'s restart behaviour comes from the service spec (`deploy.restart_policy`, with conditions `none` / `on-failure` / `any`), not from this container-level flag. ## What counts as "stopped" The distinction that trips people up is *deliberate* versus *unexpected*. `docker stop` (and `docker kill`) is deliberate: even with `always`, the daemon will not immediately bring the container back. A process that dies on its own — crash, OOM kill, a bad config, a clean `exit 0` — is unexpected, and the policy applies. Note that `on-failure` keys purely off the exit status, so a container killed by a signal (e.g. exit 137 from SIGKILL, 143 from SIGTERM) counts as a failure and will be retried. ## Guard rails the daemon applies The policy only takes effect once the container has *started successfully* — the daemon requires it to stay up briefly before it treats it as a running container worth supervising, so a container that cannot start at all doesn't spin forever at full speed. Between attempts the daemon waits an exponentially increasing delay (starting around 100 ms and doubling), so a crash-looping container costs the host far less than a tight loop would. `docker inspect -f '{{.RestartCount}}' <id>` shows how many times the daemon has restarted it. ## Choosing one Rules of thumb: long-running service on a plain Docker host → `unless-stopped`. Retryable batch job → `on-failure:N`. Anything under an external supervisor or orchestrator → `no`, so exactly one component owns restarts. `always` is mostly a legacy default; prefer `unless-stopped` unless you genuinely want the container to come back after a reboot even though an operator had taken it down. Finally, a restart policy reacts only to *process exit*. A container whose process is alive but wedged — deadlocked, not serving traffic — will never be restarted by Docker, no matter which policy you chose; a failing `HEALTHCHECK` marks a plain container `unhealthy` but does not restart it.

  • If a container's main process exits with status 0, will `--restart=on-failure` bring it back?
    No. `on-failure` acts only on a non-zero exit status; exit 0 is treated as a successful completion and the container stays in the `exited` state. If you want it restarted regardless of exit code you need `always` or `unless-stopped`. This is exactly why `on-failure` is the correct choice for batch jobs that must be allowed to finish.
  • Can you change the restart policy of a container that is already running?
    Yes — `docker update --restart=<policy> <container>` rewrites the policy in the container's host config without recreating it, and it takes effect immediately. This is the usual fix when something was started with the default `no` and needs supervision. Note that most other `docker update` fields are resource limits; restart policy is the one lifecycle setting it can change.
  • Does a failing HEALTHCHECK restart the container?
    Not with a plain Docker restart policy. The daemon flips the container's health status to `unhealthy` and reports it in `docker ps`, but restart policies fire only when the main process actually exits. Restarting on health failure requires an orchestrator (a Swarm service or a Kubernetes liveness probe) or an external watchdog.

Think of it as an employment contract with the daemon: no is a one-day gig, on-failure says come back only if you were fired, always says come back no matter what (and HR forgets your resignation every reboot), unless-stopped says come back unless you resigned.

saying these in an interview costs you the question

  • Saying `always` is the default — the default is `no`.
  • Claiming `on-failure` restarts on any exit, including 0.
  • Believing a failing HEALTHCHECK triggers a restart in plain Docker.
  • Thinking the restart policy can only be set at `docker run` time and requires recreating the container to change.
  • Combining `--restart` with `--rm` and expecting it to work.

context