skip to content

In Docker Engine, what is the practical difference between the `always` and the `unless-stopped` restart policies, and in which specific situation does that difference actually become visible?

level: middleimportance: must knowfreq 54%

answer

  1. identical until dockerd starts
  2. always: forgets you stopped it
  3. unless-stopped: remembers you stopped it
  4. reboot / daemon upgrade is the trigger
  5. docker update --restart to switch

basics

~20 s

Both restart the container on any exit. They differ only for a container you deliberately stopped: with always it comes back when the daemon restarts or the host reboots; with unless-stopped it stays down. In every other case they behave identically.

solid answer

~60 s

Day to day they are the same: both restart the container whenever its process exits, whatever the exit code, and neither restarts a container immediately after you run `docker stop` — the daemon records that the stop was deliberate. The difference shows up **only at daemon start**. When `dockerd` starts (service restart, package upgrade, host reboot), it walks the containers it knows about and starts the ones whose policy says so: - `always` — start it, even if the last thing an operator did was `docker stop` it. The "deliberately stopped" flag does not outlive the daemon. - `unless-stopped` — leave it alone if it was in a stopped state, and start it only if it was running when the daemon went down. So the failure mode people hit is: take a container down for maintenance, reboot the box, and with `always` it silently reappears. For long-lived services on a single host, `unless-stopped` is normally the safer default; `always` is mainly useful when you want "running" to be the machine's true steady state regardless of operator history.

code

bash · 9 lines
bash
docker run -d --name a --restart=always nginx:alpine
docker run -d --name b --restart=unless-stopped nginx:alpine

docker stop a b
sudo systemctl restart docker

docker ps -a --format '{{.Names}}\t{{.Status}}'
# a  Up ...      <- always came back
# b  Exited (0)  <- unless-stopped stayed down

go deeper

for a junior

Know that both keep a service running and that the only difference appears after a reboot or daemon restart for containers you had stopped.

for a middle

Explain the mechanism — the deliberate-stop mark is daemon-process state for always, persisted container state for unless-stopped — and pick unless-stopped as the sane default.

for a senior

Lead with the operational incident (maintenance stop plus a kernel-patch reboot) and mention docker update --restart as the in-place remediation plus fixing the deploy source of truth.

for a principal

Frame it as whether operator intent or declared configuration is the durable source of truth for a host, and note that under an orchestrator neither policy belongs on the container at all.

## The two policies Docker's `always` and `unless-stopped` restart policies are the two "keep this thing running" options. Both: - restart the container whenever its main process exits, **regardless of exit code** (unlike `on-failure`, which only reacts to non-zero exits); - back off exponentially between rapid restart attempts; - do **not** immediately restart a container that an operator stopped with `docker stop` or `docker kill`. That last point surprises people who expect `always` to mean *always*. When you run `docker stop`, the daemon marks the container as having been stopped on purpose, and its supervision loop honours that. So on a running host, `always` and `unless-stopped` are indistinguishable. ## Where they diverge: daemon startup The divergence is entirely in what happens when `dockerd` itself starts — a `systemctl restart docker`, a Docker Engine package upgrade, or a host reboot. At startup the daemon reads the state of every container it manages and decides which to bring up: - **`always`**: bring it up unconditionally. The "deliberately stopped" mark is in-memory state of the previous daemon process; it does not survive. Result: a container you stopped last week reappears after a reboot. - **`unless-stopped`**: bring it up only if it was *running* when the daemon went away. A container in the `exited` state because a human stopped it stays exited. That is the whole difference. It has nothing to do with exit codes, crashes, or backoff — only with reconciling desired state at daemon start. ## Why it matters operationally The classic incident: an operator takes a service down for maintenance (`docker stop payments`), leaves it down, and days later the host reboots after a kernel patch. If the policy is `always`, the payments container comes back with the old configuration and no one intended it to be running. If it is `unless-stopped`, the box comes up in the state the operator left it. The mirror-image case argues for `always`: a machine whose *only* correct state is "these containers are running". Perhaps a kiosk, an edge box, or a single-host appliance where nobody should ever be able to leave a service down by accident. There, `always` acts as a self-healing reset — whatever a human did before the reboot, the machine returns to its intended shape. Some teams deliberately pick `always` for exactly that reason. A useful way to phrase the choice in an interview: `unless-stopped` treats *operator intent* as durable state; `always` treats the *declared configuration* as the only truth and discards operator intent at every daemon start. ## Interactions worth knowing **Neither reacts to health checks.** A container with `always` whose process is alive but wedged — deadlocked thread pool, stuck event loop — is never restarted by Docker. Restart policies watch process exit, nothing else. A failing `HEALTHCHECK` only flips the reported health status. **Both use the same backoff.** If the container crashes immediately on start, the daemon spaces retries with an exponentially growing delay rather than hammering the host, and `docker inspect -f '{{.RestartCount}}'` shows the accumulated count. **Both are changeable in place.** `docker update --restart=unless-stopped <container>` switches an existing container from one policy to the other without recreating it — the usual remediation once you discover a fleet of `--restart=always` containers. **Compose and Swarm differ.** In a Compose file the `restart:` key takes the same values. In Swarm mode, however, `deploy.restart_policy` on a service uses a different vocabulary (`condition: none | on-failure | any`) and is evaluated by the orchestrator, not by the local daemon's container-level policy; `restart:` is ignored when the stack is deployed to Swarm. **Both are wrong under an external supervisor.** If a systemd unit or an orchestrator already starts and stops the container, an `always`/`unless-stopped` policy gives you two supervisors fighting over the same object — the classic symptom being a container that refuses to stay stopped. Pick `no` and let the outer layer own it. ## Quick decision rule Long-running service on a plain Docker host, humans occasionally stop things on purpose → `unless-stopped`. Appliance-style host where running is the only acceptable state → `always`. Anything supervised from outside → `no`. Retryable batch job → `on-failure:N`.

  • With `--restart=always`, why doesn't the container come back immediately after `docker stop`?
    Because the daemon distinguishes a deliberate stop from an unexpected exit and records that the container was stopped on purpose, suppressing its supervision loop for that container. That suppression lives in the running daemon's state, so it is lost when the daemon restarts — which is exactly why the container reappears after a reboot. `unless-stopped` instead derives the decision from the persisted container state, so it survives.
  • You inherit a host where every container was created with `--restart=always` and you want `unless-stopped` instead. What do you do?
    Run `docker update --restart=unless-stopped` against the containers; it rewrites the policy in place, no recreation or downtime needed. Then fix the source of truth — the Compose file, provisioning script or image-deploy tooling — otherwise the next deploy recreates them with `always` again.

unless-stopped is a light switch: after a power cut, it stays off if you turned it off. always is a motion-sensor light: after the power comes back it turns on regardless of what you did before.

saying these in an interview costs you the question

  • Claiming `always` restarts a container the moment you `docker stop` it.
  • Saying the two policies differ in how they treat exit codes — they don't; both ignore the exit code.
  • Thinking `unless-stopped` won't restart a container after a reboot at all (it does, if the container was running).
  • Assuming either policy restarts an unhealthy-but-alive container.
  • Believing you must recreate the container to change between the two.

context