Docker Restart Policies Explained: always, unless-stopped, on-failure, no
AI generated
FROM
RUN
Docker · Operations · Container Lifecycle
Docker Restart Policies Explained
always, unless-stopped, on-failure, no

A container that does not restart after a crash is a silent outage in production. Docker offers four restart policies that look similar at first glance but behave quite differently in practice, especially around manual stops and daemon restarts.

17 min read restart policy always unless-stopped on-failure systemd

1. Why restart policies exist in the first place

Containers are deliberately designed to be short lived. A process inside a container can terminate for many reasons: an unhandled error in the application, an out-of-memory kill by the kernel, a failed health check, or simply a bug in the code. Without built in restart logic, an external process, such as a cron job or a monitoring script, would have to detect the failure and manually bring the container back up. That is error prone and slow, especially for outages that happen overnight without anyone on call.

Restart policies move that responsibility into the Docker daemon itself. The daemon observes the exit code and container status and decides, based on the configured policy, whether and when to restart. This works on a single host without any orchestrator like Kubernetes or Swarm, which is why it is the first line of defense against failures for single host setups using docker run or docker compose.

2. always: unconditional restart on every stop

The always policy is the most aggressive option. The container restarts after every termination, regardless of the exit code, and is also automatically brought back up the next time the Docker daemon itself starts, for example after a server reboot. That makes always the right choice for permanently running services such as web servers, databases, or reverse proxies, where downtime should be as short as possible.

The catch lies in the word unconditional: even after a manual docker stop, the container comes back the next time the daemon restarts, because Docker remembers the last desired state. Anyone who stops an always container for testing and then reboots the server will be surprised to see it running again. For maintenance windows where a service should intentionally stay down, always is therefore unsuitable unless the policy is explicitly changed beforehand.


# Start a container with the always policy
docker run -d --name webserver --restart always nginx:1.27

# Check the policy afterwards
docker inspect webserver --format '{{.HostConfig.RestartPolicy.Name}}'
# Output: always

# Manual stop: the container stays stopped UNTIL the daemon restarts
docker stop webserver
docker ps -a --filter name=webserver
# STATUS: Exited (0)

# After a Docker daemon restart (e.g. systemctl restart docker
# or a server reboot), the container starts again automatically

3. unless-stopped: always with a memory for manual stops

unless-stopped behaves almost identically to always, with one crucial difference: if the container is explicitly terminated via docker stop, Docker remembers this state across a daemon restart. When the server reboots, a manually stopped container stays stopped instead of automatically coming back up. Only an explicit docker start returns it to the active state, and from then on the normal automatic restart logic applies again.

In practice, unless-stopped is the better default over always for most production long running services, because it respects human intent: an administrator who deliberately shuts a service down for maintenance does not expect it to simply reappear after the next server restart. Compose setups with multiple services benefit especially from this, since individual containers can be taken offline on purpose without an accidental host reboot bringing them back.


# docker-compose.yml
services:
  app:
    image: mironsoft/app:latest
    restart: unless-stopped
    ports:
      - "8080:8080"

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - redis-data:/data

volumes:
  redis-data:

4. on-failure: restart only on a genuine error

on-failure restarts a container only when the process ends with a non zero exit code, signaling an error. A clean, intentional exit with code 0 does not trigger a restart. That makes on-failure the right fit for batch jobs, migration scripts, or worker processes that are meant to end normally once their work is done, but should retry after crashing due to a network error or an unreachable database.

Optionally, the number of restart attempts can be limited to avoid infinite loops for jobs that are permanently broken. Without a limit, Docker keeps retrying indefinitely with exponentially increasing delays between attempts, which for a structurally broken container, for example one with an invalid configuration, leads to a pointless restart loop that wastes log space and CPU time.


# Migration job: restart only on failure, max 5 attempts
docker run -d --name db-migration \
  --restart on-failure:5 \
  mironsoft/migration-runner:latest

# On a clean exit (code 0), the container simply stays stopped
docker run --name one-shot-report --restart on-failure \
  mironsoft/report-generator:latest
docker wait one-shot-report
echo $?   # 0 -> no restart happened

5. no: the quiet default setting

no is Docker's default when no restart policy is specified. The container never restarts automatically under any circumstances, neither after a crash nor after a daemon restart. That sounds like the least safe choice at first, but it is exactly right for interactive containers, one off CLI invocations, or debugging sessions, where nobody expects a surprise restart.

The most common mistake in practice is using no unintentionally, simply because the policy was forgotten. A web server container without a restart flag runs perfectly normally until it crashes once or the host reboots, and then stays silently offline until someone notices the outage manually and fixes it. Especially with docker run outside a Compose file, the missing policy is easy to overlook, which is why every restart flag in deployment scripts deserves a deliberate look.

6. How restart policies interact with daemon and host restarts

A central, often overlooked aspect: restart policies do not only apply to process crashes within a running system, they also apply when the Docker daemon itself starts. When the server reboots or the dockerd service is restarted via systemctl restart docker, Docker walks through its list of containers and starts every one whose policy and last known state call for it. For always, that means practically always. For unless-stopped: unless the container was manually stopped beforehand.

For this mechanism to work at all, the Docker daemon itself must be enabled to start on boot, typically via systemctl enable docker. If the daemon is not enabled, every container stays offline after a reboot no matter which restart policy is configured, because the daemon never even starts to bring them back. This systemd level detail is frequently missing from operations documentation, even though it is the basic prerequisite for any restart policy to matter.


# Permanently enable the Docker daemon (prerequisite for all restart policies)
sudo systemctl enable docker
sudo systemctl status docker

# Test: list all containers with their policy
docker ps -a --format 'table {{.Names}}\t{{.Status}}'
docker inspect $(docker ps -aq) \
  --format '{{.Name}}: {{.HostConfig.RestartPolicy.Name}}'

7. Restart policies and docker compose up -d

In Compose environments there is an additional nuance: docker compose up -d respects the restart policy when restarting an already running stack, but docker compose down removes the containers entirely, making their policy irrelevant for those instances. Only the next docker compose up creates new containers with whatever policy is currently defined in the YAML file. Anyone who changes the restart setting in the Compose file must recreate the containers, a plain docker compose restart is not enough.

Another point: health checks and restart policies operate independently. A container that is running but reported as unhealthy by its health check is not automatically restarted by the restart policy, because from the Docker daemon's perspective the process is still running. Anyone who wants to react to failed health checks needs additional logic, for example through an orchestrator, a Watchtower style tool, or a custom supervisor script that explicitly restarts the container when needed.

8. Common mistakes and how to avoid them

A classic mistake is using always for one off jobs. A backup script with always restarts immediately after every run, even after completing successfully, because always makes no distinction between a successful and a failed exit. The result is a container that restarts every few seconds and wastes resources and log storage, a pattern administrators often only discover through unusually high CPU load.

Equally problematic is using unless-stopped for containers that are meant to be intentionally temporary, such as test or staging instances. After an accidental server reboot, these containers suddenly reappear and occupy ports or resources that were supposed to be free. As a rule of thumb: on-failure for jobs with a clear successful end state, unless-stopped for permanent services that respect deliberate manual intervention, always only when every single stop is genuinely unwanted, and no for everything interactive and temporary.

9. Practical recommendation by application type

For a production web server or API that must stay permanently reachable, unless-stopped is the pragmatic default: automatic restarts after crashes and reboots, while still respecting an intentional manual stop during maintenance windows. For critical infrastructure containers such as a reverse proxy that must never stay down unintentionally, always can make more sense, combined with clear documentation stating that a stop must temporarily change the policy.

For batch processing, database migrations, cron style one off jobs, and CI/CD build containers, on-failure with a sensible retry limit is the right choice, since it distinguishes between a genuine error and a normal end. And for anything started interactively, such as a debug shell container or a local development container, no remains the right, unobtrusive choice. The table below summarizes this decision once more.

Policy Restart after crash Restart after daemon restart Typical use case
no (default) No No Interactive containers, debugging, one off CLI runs
on-failure[:max] Yes, only on exit code != 0 Yes, if last active Batch jobs, migrations, CI build containers
unless-stopped Yes, always Yes, unless manually stopped Production long runners: web servers, APIs, Redis
always Yes, always Yes, unconditionally Critical infrastructure with no accepted downtime

Mironsoft

Container infrastructure, CI pipelines and deployment automation

Docker setups that hold up across the team and in production?

We review existing Dockerfiles and Compose stacks for security gaps, bloated images and fragile build pipelines, then build a container infrastructure that builds fast, runs securely and stays understandable across the team.

Dockerfile Review

Systematically optimizing multi-stage builds, layer caching and image size.

Security Audit

Hardening container isolation, secrets handling and image scanning against real attack surfaces.

CI/CD Integration

Building build pipelines, registries and deployment strategies for reproducible releases.

10. Summary

Docker Restart Policies: Key Takeaways

always

Restarts after every stop and every daemon restart, even after a manual docker stop.

unless-stopped

Like always, but respects a deliberate manual stop across reboots.

on-failure

Restarts only on a failure exit code, ideal for jobs with a defined success state.

no

The default when unspecified: no automatic restart, fitting for interactive containers.

11. FAQ: Docker Restart Policies: Key Takeaways

1What is Docker's default restart policy if I don't specify one?
Without an explicit setting, Docker uses the no policy. The container does not automatically restart after a crash or a Docker daemon restart, it simply stays in the Exited state until someone starts it manually again.
2Does a container with always restart even after a manual docker stop?
Yes, that is exactly the difference from unless-stopped. With always, Docker does not remember a manual stop state, so the container comes back the next time the Docker daemon restarts or after a server reboot, even if it was deliberately stopped beforehand.
3Can I change the restart policy of a running container afterwards?
Yes, docker update --restart unless-stopped changes the policy without needing to recreate the container. The container does not need to be stopped for this, the new policy applies immediately to future restart decisions.
4What happens with on-failure if the container exits cleanly with code 0?
Then no restart happens, because on-failure only reacts to a non zero exit code. A normally finished batch job or a successfully completed migration script simply stays in the Exited (0) state.
5How do I limit the number of restart attempts with on-failure?
Through the syntax on-failure:N, where N is the maximum number of attempts, for example --restart on-failure:5. Without this limit, Docker keeps retrying indefinitely, with exponentially increasing pauses between attempts.
6Do restart policies also apply when the Docker daemon itself restarts?
Yes, that is actually one of their main purposes. When dockerd starts, for example after a server reboot, Docker walks through its list of existing containers and automatically starts every one whose policy and last known state call for it, provided the Docker service itself is enabled via systemctl enable docker.
7Does the restart policy react to a failed health check?
No, health checks and restart policies are separate mechanisms. A container that is marked unhealthy by its health check but whose main process is still running is not touched by the restart policy. Reacting to that requires additional tooling like an orchestrator or a custom supervisor script.
8Which policy fits best for a cron job style container?
For cron job style one off tasks, no or on-failure with a low limit usually makes the most sense, since the container is meant to end normally once its work is done. The actual scheduling then comes from outside, for example the host cron or a scheduling tool, not from the restart policy itself.
9What happens with always to a container that crashes in an infinite loop?
Docker keeps trying to restart it, with increasing backoff pauses between attempts. That prevents CPU load from restarting every few milliseconds, but it still results in a permanent restart cycle that should stand out in logs and monitoring.
10Do I need to set the restart policy for every container in Compose individually?
Yes, restart is a per service setting in docker-compose.yml and does not apply globally to the whole stack. Every service can get its own policy suited to its purpose, for example unless-stopped for the web server and on-failure for an accompanying migration job.