Restart Policies
Docker restart policies tell the Docker daemon whether to start a container again after its main process exits or after the daemon starts. They matter because a useful service should usually recover from a crash or host reboot without someone manually running docker start.
A restart policy is not a health check, deployment system, or application supervisor. It is a simple rule attached to one container that says what Docker should do when that container stops.
Overview: How Restart Policies Work
A Docker image is a read-only template made of filesystem layers and metadata. A container is an instance of that image with its own writable layer, name, environment, mounts, network configuration, port publications, and one main process. Restart policies belong to the container configuration, not to the image. Two containers created from the same image can have different restart behavior.
When you run a container, Docker starts the configured command as the container’s main process. If that process exits, the container stops and receives an exit code. Exit code 0 usually means success. A nonzero exit code usually means an error, although applications can define their own meanings. The Docker daemon watches that main process and applies the restart policy when the process exits.
The four common policies are no, on-failure, always, and unless-stopped. The default is no, which means Docker leaves the container stopped. on-failure restarts only when the container exits with a nonzero status, and it can include a maximum retry count such as on-failure:3. always restarts the container whenever it stops, and also starts it when the Docker daemon starts. unless-stopped is similar to always, but it respects a manual stop across daemon restarts.
The difference between always and unless-stopped is one of the most important details. If a container with always is manually stopped and the Docker daemon later restarts, Docker starts it again. If a container with unless-stopped is manually stopped, Docker remembers that choice and does not bring it back merely because the daemon restarted. For long-running local services and simple single-host deployments, unless-stopped is often the friendlier default.
Restart policies are implemented by the Docker daemon, so they work even if your terminal closes. On Linux, the daemon manages container processes through the container runtime, namespaces, and cgroups. On Docker Desktop for macOS and Windows, Linux containers run inside Docker’s managed Linux VM, but the policy behavior from the CLI is the same.
Restart policies only apply to containers that Docker has already created. They do not pull newer images, rebuild images, change environment variables, recreate volumes, or migrate data. If an image tag in a registry changes, restarting an existing container does not replace its filesystem. To deploy new image content, pull or build the new image and recreate the container, or use docker compose up -d from updated configuration.
Syntax
docker run --restart POLICY IMAGE[:TAG] [COMMAND] [ARG...]
docker update --restart POLICY CONTAINER [CONTAINER...]
| Policy | Meaning |
|---|---|
no |
The default. Do not restart the container automatically. |
on-failure |
Restart only if the main process exits with a nonzero exit code. |
on-failure:N |
Restart after failure, but stop retrying after N failed restarts. |
always |
Restart whenever the container stops, and start it when the Docker daemon starts. |
unless-stopped |
Restart like always, except do not restart a container that was manually stopped. |
docker update --restart |
Changes the restart policy of an existing container without recreating it. |
restart: |
Compose service key for the same single-container restart policies. |
Use docker run --restart ... when creating a new container. Use docker update --restart ... when the container already exists and only the policy needs to change. In Compose, put the policy under the service with restart: unless-stopped or a similar value.
Examples
Example 1: Keep a Web Server Running
docker run -d --name restart-web \
--restart unless-stopped \
-p 8080:80 \
nginx:1.27-alpine
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' restart-web
Output:
8d7a6f5e4d3c2b1a09876543210fedcba9874f8b2c1d9a0e5c7b6d3a2f1e0b9c
unless-stopped
This creates an Nginx container with a specific image tag and publishes host port 8080 to container port 80. The --restart unless-stopped policy tells Docker to bring it back after crashes and daemon restarts, unless you intentionally stopped it with docker stop restart-web. The docker inspect command reads the policy stored in the container’s host configuration.
Example 2: Retry a Failing Job a Limited Number of Times
docker run -d --name retry-demo \
--restart on-failure:3 \
alpine:3.20 \
sh -c 'echo "starting"; exit 1'
sleep 2
docker inspect --format '{{.RestartCount}} {{.State.Status}} {{.State.ExitCode}}' retry-demo
Output:
5f4e3d2c1b0a9876543210fedcba9878d7a6f5e4d3c2b1a09876543210fedcba
3 exited 1
The Alpine container immediately exits with status 1. Because the policy is on-failure:3, Docker retries it after failures and then stops after the retry limit is reached. This policy is useful for jobs where a temporary dependency might recover, but endless restarts would hide the real problem.
Example 3: Change an Existing Container’s Policy
docker update --restart always restart-web
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' restart-web
Output:
restart-web
always
docker update changes the restart policy on an existing container. It does not rebuild the image, recreate the container, change its ports, or restart the process by itself. After this change, Docker will start restart-web whenever the daemon starts, even if the container had previously been manually stopped.
Example 4: Set a Restart Policy in Compose
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
restart: unless-stopped
Output:
[+] Running 2/2
Network restart-demo_default Created
Container restart-demo-web-1 Started
With Compose, the restart policy is part of the service definition. Running docker compose up -d creates the container with that policy. The modern command is docker compose, not the old standalone docker-compose binary. Compose is the better choice when the service also needs repeatable ports, environment variables, networks, and volumes.
How It Works Step by Step
- You create a container with
docker run --restart unless-stopped ..., or Compose creates one from a service definition. - The Docker CLI sends the requested restart policy to the Docker daemon as part of the container configuration.
- The daemon creates the container by mounting the image’s read-only layers and adding a thin writable layer, then prepares networking, mounts, environment variables, and the configured command.
- The daemon starts the container’s main process and tracks its state.
- If the process exits, Docker records the exit code and updates the container state.
- The restart manager checks the policy. With
no, it does nothing. Withon-failure, it checks for a nonzero exit code. Withalwaysorunless-stopped, it schedules a restart unless the manual-stop rule prevents it. - Docker waits briefly before restarting. Repeated rapid failures are delayed so a broken container does not spin as fast as the CPU allows.
- If the Docker daemon starts after a host reboot or daemon restart, it evaluates containers with restart policies and starts the ones whose policy says they should be running.
The policy watches the container’s main process only. If your app starts a background worker and the foreground process exits successfully, Docker sees the container as stopped. If a web server stays alive but is internally unhealthy, Docker does not automatically know that from the restart policy alone. Health checks and orchestrators can add deeper service supervision, but they are separate mechanisms.
Common Mistakes
Using a Restart Policy to Hide a Bad Command
docker run -d --name broken-loop --restart always alpine:3.20 sh -c 'echo bad config; exit 1'
This creates a container that repeatedly fails and restarts. The policy is doing exactly what you asked, but the service is still broken. Inspect logs and state instead of assuming automatic restart means automatic recovery:
docker logs broken-loop
docker inspect --format '{{.RestartCount}} {{.State.Status}} {{.State.ExitCode}}' broken-loop
Choosing always When Manual Stops Should Be Respected
docker run -d --name local-cache --restart always redis:7.4-alpine
This can surprise you on a workstation: if you manually stop the container and later restart Docker Desktop or the Docker daemon, Docker may start it again. For local long-running services, unless-stopped usually matches intent better:
docker update --restart unless-stopped local-cache
Expecting Restart to Update an Image
docker pull nginx:1.27-alpine
docker restart restart-web
Pulling image content does not mutate existing containers. The stopped or restarted container still uses the image content it was created with. Recreate the container when you need new image content or changed runtime options:
docker stop restart-web
docker rm restart-web
docker run -d --name restart-web --restart unless-stopped -p 8080:80 nginx:1.27-alpine
Forgetting That Data Still Needs Volumes
docker run -d --name db-no-volume --restart unless-stopped postgres:16-alpine
A restart policy can restart the database process, but it is not a persistence strategy. Important database files should live in a named volume, and real passwords should be provided as obvious placeholders in examples or through a secret mechanism in production:
docker volume create pgdata
docker run -d --name db-with-volume \
--restart unless-stopped \
-e "POSTGRES_PASSWORD=changeme" \
-v pgdata:/var/lib/postgresql/data \
postgres:16-alpine
Best Practices
- Use
unless-stoppedfor most simple long-running services on a single Docker host. - Use
on-failure:Nfor short jobs or workers where limited retrying is useful but infinite loops are harmful. - Use
alwaysonly when the container should return after daemon startup even if it was manually stopped before. - Inspect
RestartCount, exit code, and logs when a service keeps coming back. A high restart count is a symptom to debug. - Pin image tags such as
nginx:1.27-alpine,alpine:3.20, andpostgres:16-alpine. Thelatesttag is a moving target and makes recovery harder to reason about. - Store durable data in named volumes. Restart policies preserve availability, not data correctness.
- Keep one main foreground process in the container. Docker restarts the container when that process exits.
- Use Compose for repeatable local or single-host services so the restart policy sits beside ports, mounts, networks, and environment variables.
- Do not rely on restart policies as a replacement for health checks, monitoring, backups, or orchestration in production systems.
Practice Exercises
- Run an
nginx:1.27-alpinecontainer namedpractice-restart-webwith--restart unless-stopped, then inspect the policy. Expected end state: inspection printsunless-stopped. - Create a container from
alpine:3.20that exits with status1and uses--restart on-failure:2. Hint: checkRestartCountafter a short delay. - Write a
compose.ymlservice forredis:7.4-alpinewithrestart: unless-stopped. Expected end state:docker compose up -dstarts the service anddocker inspectshows the policy on the created container.
Summary
- Restart policies are container-level rules stored by the Docker daemon.
- The default policy is
no, so containers do not restart automatically unless you configure them to. on-failureresponds to nonzero exit codes and can include a retry limit.alwaysrestarts aggressively and starts containers when the daemon starts.unless-stoppedis likealways, but it respects an intentional manual stop.- Restarting a container does not update its image, ports, mounts, environment, or data strategy.
- Use logs, inspection, volumes, pinned image tags, and Compose alongside restart policies for reliable services.
