A container without a restart policy stays down after it crashes or after you reboot the VPS. A restart policy tells the Docker daemon to bring it back for you. This guide explains the four policies, how they behave in practice, and how to set or change them without recreating your containers.
Before you start
- A Linux VPS with Docker Engine and the Compose plugin. See Install Docker and Docker Compose if you still need them.
- At least one container you want to keep running.
- A user that can run
dockercommands.
The four restart policies
no(the default): Docker never restarts the container on its own.on-failure[:max-retries]: restart only when the main process exits with a non-zero code, which usually means a crash. You can cap the number of attempts, for exampleon-failure:5.always: restart whenever the container stops, for any reason. If you stop it by hand, it stays stopped until the Docker daemon restarts, and then it starts again.unless-stopped: likealways, except a container you stopped by hand stays stopped after a daemon restart or reboot.
For most web apps, databases and background services on a VPS, unless-stopped is the right choice. It recovers from crashes and reboots, but it respects your decision when you stop something on purpose.
How the policies behave after a reboot
When the VPS boots, systemd starts the Docker service. The daemon then looks at every container and starts the ones whose policy says they should run:
always: started, even if you had stopped it before the reboot.unless-stopped: started only if it was running when the server went down.on-failure: not started after a clean reboot, because the container did not fail. Use it for jobs that should only retry on errors.no: not started.
All of this depends on Docker itself starting at boot. On most installs it does. Confirm it:
systemctl is-enabled dockerIf the output is disabled, enable it:
sudo systemctl enable dockerNote: Docker waits about ten seconds of uptime before it treats a restart as successful. A container that crashes again within that window gets an increasing delay between attempts, starting at 100 ms and doubling each time, so a broken container does not hammer the CPU.
Set a policy with docker run
Add --restart when you create the container:
docker run -d --name web --restart unless-stopped -p 8080:80 nginx:stableFor a retry limit:
docker run -d --name worker --restart on-failure:5 myworker:1.0Set a policy in Docker Compose
In compose.yaml, use the restart key on each service:
services:
app:
image: myapp:1.0
restart: unless-stopped
db:
image: postgres:16
restart: unless-stoppedApply the change:
docker compose up -dCompose recreates any service whose configuration changed.
Tip: Quote "no" in YAML (restart: "no"). Without quotes, YAML can read no as the boolean false.
Change the policy on a running container
You do not need to recreate a container to change its policy. docker update changes it in place:
docker update --restart unless-stopped webTo apply the same policy to every running container at once:
docker update --restart unless-stopped $(docker ps -q)If the container is managed by Compose, also change the restart key in the file. Otherwise the next docker compose up -d puts the old value back.
Restart policies are not health checks
A restart policy only reacts when the main process exits. If the app hangs but the process keeps running, Docker sees nothing wrong and does nothing. A container marked unhealthy by a health check is also not restarted by plain Docker Engine.
To catch hangs, add a health check and make your app exit when it fails, or use an external monitor. Add health checks to Docker containers explains the options.
Check it works
See the policy each container has:
docker inspect --format '{{.Name}} {{.HostConfig.RestartPolicy.Name}}' $(docker ps -aq)Then test a crash. Kill the main process and watch Docker restart it:
docker kill web
docker ps --filter name=webWarning: docker kill counts as a manual stop, so unless-stopped and always will not restart it until the daemon restarts. To simulate a real crash, run docker exec web kill 1 instead, then check docker ps again after a few seconds.
The best test is a planned reboot during a quiet period:
sudo rebootAfter you reconnect, docker ps should list every container with unless-stopped or always as Up.
Troubleshooting
- Containers do not start after a reboot: the Docker service is not enabled, or the containers have policy
no. Check withsystemctl is-enabled dockerand the inspect command above. - Container shows
Restarting (1)forever: the app crashes on start. Readdocker logs --tail 50 <name>and fix the cause. Fix a Docker container that exits immediately lists the usual reasons. - A container you stopped came back: it has policy
always. Switch it tounless-stoppedwithdocker update. - Policy reverted after a deploy: the Compose file still has the old
restartvalue. Update the file, not just the container.
Next steps
- Make health part of your setup: Add health checks to Docker containers.
- Prefer systemd control over whole stacks? Read Start Docker Compose stacks on boot with systemd.
