E-NO
Docker Restart Policies capacity planning 10 Min Read

Docker Restart Policies: A Practical Guide to Capacity Planning

calendar_today Published: 2026-09-25
update Last Updated: 2026-09-25
analytics SEO Efficiency: 100%
Technical guide illustration for Docker Restart Policies: A Practical Guide to Capacity Planning.

Intro

Docker restart policies control whether containers automatically restart after they exit. They are critical for keeping services running and recovering from failures. But restart policies alone do not guarantee application availability. You also need to think about capacity: how many containers, how much CPU and memory, how many restart attempts, and how to avoid restart loops that waste resources.

This article combines restart policy configuration with capacity planning. You will see concrete commands, configuration snippets, and worked examples. The goal is operational safety: observe before changing, limit the blast radius, use placeholders instead of secrets, verify the result, and document how to recover if the expected state is not reached.

This guide is for developers, DevOps engineers, and technical startup teams who run Docker in production or production-like environments. By the end, you will be able to configure restart policies that match your workload, set resource limits to prevent noisy neighbors, and plan for failure without over-provisioning.

Version and Environment Inventory

Before touching restart policies or capacity, establish a baseline. Know what Docker version you are running, what containers exist, and what resources they use. This prevents surprises and gives you a rollback point.

Start with read-only commands:

docker version

Expected output shows client and server versions. Note the API version; restart policy behavior is stable across recent versions, but swarm mode and compose file versions matter.

List running containers:

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

The status column shows restart counts, for example "Up 2 hours (restarting 3 times)". That is a red flag.

Inspect a specific container to see its current restart policy and resource limits:

docker inspect <container> --format '{{.HostConfig.RestartPolicy}} {{.HostConfig.Memory}} {{.HostConfig.NanoCpus}}'

Expected output: {no 0 0} if no policy, or {always 1073741824 500000000} meaning always restart, 1 GB memory, 0.5 CPU.

For Docker Compose projects, use:

docker compose ps
docker compose logs -f <service>
docker compose exec <service> sh

Also check where files are stored. Named volumes (e.g., app_data:/var/lib/app) are managed by Docker and easier to reuse across container rebuilds. Bind mounts (e.g., ./data:/var/lib/app) map directly to a host path, useful for development but can cause permission and portability problems. Confirm data persistence with a restart test: stop the container, recreate it, and ensure the application still sees expected files. If data disappears, the service was writing to the container filesystem rather than a volume or mount.

Run a small production-like local test to verify persistence before rolling changes to staging or production.

Quick check 1 of 2

According to the restart policy details, when does a restart policy take effect?

The passage states that a restart policy only takes effect after a container starts successfully, meaning it is up for at least 10 seconds and Docker has started monitoring it.

Safe Configuration Path

Changing restart policies and resource limits requires a deliberate path. First, capture the current state. Then make one scoped change, verify it, and document recovery.

Choosing a Restart Policy

Docker supports four restart policy values:

  • no: Do not automatically restart the container (default).
  • on-failure[:max-retries]: Restart only if the container exits with a non-zero exit code. Optionally limit the number of restart attempts. For example, on-failure:5 restarts at most 5 times.
  • always: Always restart the container regardless of exit code. If stopped manually, it restarts only when the Docker daemon restarts or the container is manually started.
  • unless-stopped: Similar to always, but if the container was stopped manually before the daemon restarted, it will not be restarted.

Use unless-stopped for most long-running services. It avoids unexpectedly restarting containers that were intentionally stopped for maintenance. Use on-failure for batch jobs or one-off tasks where infinite restarts could loop. Avoid always unless you have a specific reason, because it can mask configuration errors by repeatedly restarting a broken container.

Example: run a web server with unless-stopped and limit restarts:

docker run -d --name web \
  --restart unless-stopped \
  --memory 512m \
  --cpus 0.5 \
  nginx:alpine

For a database that should not auto-restart on data corruption, use on-failure:3:

docker run -d --name db \
  --restart on-failure:3 \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

In Docker Compose, declare policies under the service:

services:
  web:
    image: nginx:alpine
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

Note: restart is ignored in swarm mode; use deploy.restart_policy instead.

Capacity Planning Basics

Capacity planning is not just about restart policies; it is about ensuring containers have enough resources to run and that the host can handle the load. Set memory and CPU limits on every container to prevent a single container from exhausting the host.

Memory limits: Use --memory and --memory-swap. If a container exceeds its memory limit, the kernel may kill the process (OOM). Example:

docker run -d --name app --memory 1g --memory-swap 2g myapp

CPU limits: Use --cpus to limit the number of CPU cores. Example: --cpus 1.5 allows 1.5 cores. You can also use CPU shares for relative weighting.

Monitor actual usage with docker stats:

docker stats --no-stream

Output shows CPU %, memory usage, and limit. Use this to right-size limits.

Consider restart loops: if a container repeatedly exits and restarts, it may consume CPU cycles. Configure on-failure with a maximum retry count and combine with a healthcheck to avoid infinite loops.

Implementing Changes Safely

When changing policies, do it in this order:

  1. Record current state: docker inspect <container> > before.json
  2. Make the change: recreate container or update compose file and docker compose up -d
  3. Verify: check restart policy and resource limits with docker inspect
  4. Test failure: manually stop the container and see if it restarts as expected
  5. Rollback: if needed, use the saved before.json to recreate the original configuration

Never edit a running container directly. Always recreate from a known configuration (Dockerfile, compose file, or run command).

Verification and Diagnostics

After configuring restart policies and resource limits, verify that they work as intended. Use a combination of commands to observe behavior.

Simulating a Failure

To test a restart policy, stop the container and observe:

docker stop web
docker ps -a

If the policy is unless-stopped, the container will not restart immediately because it was manually stopped. To test failure restart, kill the main process instead:

docker exec web kill 1

Then check docker ps after a few seconds: the container should be running again.

For on-failure, simulate a non-zero exit by running a container that exits with error:

docker run --name failtest --restart on-failure:2 alpine sh -c 'exit 1'

Check the restart count:

docker inspect failtest --format '{{.RestartCount}}'

It should be 2 (initial run plus one restart) and then stop retrying.

Diagnosing Restart Loops

A container stuck in a restart loop shows a rapidly increasing restart count. Common causes:

  • Broken configuration (e.g., wrong environment variable)
  • Missing dependencies (database not ready)
  • OOM kills because memory limit too low
  • Application crashes due to bug

Use logs to find the reason:

docker logs web --tail 100

Check docker inspect for OOM kills:

docker inspect web --format '{{.State.OOMKilled}}'

If true, increase memory limit or fix memory leak.

Use healthchecks to prevent routing traffic to an unhealthy container. Example Dockerfile:

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

In Compose:

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost/"]
  interval: 30s
  timeout: 3s
  retries: 3

A healthy container with a restart policy is more resilient.

Observing Resource Usage

To plan capacity, monitor actual usage over time. Use docker stats periodically or integrate with monitoring tools like Prometheus and cAdvisor. For a quick snapshot:

docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"

Note the memory percentage relative to the limit. If consistently above 80%, consider raising the limit or optimizing the application.

Failure Modes and Recovery

Even with good restart policies, failures occur. Understand common failure modes and how to recover.

Restart Policy Pitfalls

  • Infinite restart loops: Without a max retry count, a broken container can restart forever, consuming CPU and filling logs. Use on-failure with a limit for tasks that should eventually give up.
  • Masking configuration errors: always or unless-stopped may keep a container running but in a bad state. Monitor logs and healthchecks to catch these.
  • Stateful containers: Restarting a database container without proper data persistence can lead to data loss. Always use volumes and test persistence.
  • Dependency ordering: If a container restarts before its dependency is ready, it may fail again. Use depends_on with condition in Compose (in newer versions) or an init container.

Recovery Procedures

If a container is in a restart loop:

  1. Stop the container to break the loop: docker stop <container>
  2. Inspect logs to find the root cause: docker logs <container>
  3. Fix the issue: update configuration, increase memory, fix code, or wait for dependency
  4. Start the container manually: docker start <container>
  5. Verify it stays up and healthy.

If the host is out of resources (OOM), identify the culprit with docker stats and docker events --filter event=oom. Reduce limits on other containers or add capacity.

For stateful services, practice recovery: simulate a container loss and restore from backup. Ensure backups are tested regularly.

Quick check 2 of 2

What happens if you manually stop a container while it has a restart policy?

The passage explains that if you manually stop a container, the restart policy is ignored until the Docker daemon restarts or the container is manually restarted.

Operations Checklist

Use this checklist before and after making changes to restart policies and capacity settings. Assign an owner to each item and review at least monthly.

ItemOwnerFrequency
Review restart policies for all production containersDevOps lead (e.g., Priya Shah)Monthly
Check restart counts and identify loopsOn-call engineerDaily via monitoring
Validate memory and CPU limits against actual usageCapacity plannerWeekly
Test data persistence and backup restorationDatabase administratorQuarterly
Simulate container failure and verify auto-restartQA engineerAfter each release
Update runbooks with recovery stepsTech writer or DevOps leadWhen changes occur

For each item, document the current state, the expected state, and the command to verify. Keep a log of changes with timestamps and owners.

Common Pitfalls and How to Avoid Them

Pitfalls often arise from misconfiguration or misunderstanding of restart policies and resource limits.

1. Ignoring restart loops

Why it happens: Developers set always without a backoff or monitoring. A container crashes on startup due to a missing config, and it loops forever, consuming CPU and filling logs.

How to avoid: Use on-failure with a max retry count for non-critical services. For critical services, use healthchecks and alerting on restart counts. Set log rotation to prevent disk exhaustion.

2. Not limiting memory and CPU

Why it happens: Teams forget to set limits, or assume the host has enough resources. One container with a memory leak can cause the kernel to kill other processes.

How to avoid: Always set --memory and --cpus for production containers. Use docker stats to monitor usage and adjust limits. Consider using a container orchestration platform (Kubernetes, Swarm) that enforces resource quotas.

3. Misunderstanding always vs unless-stopped

Why it happens: Users think always is appropriate for all services, but it restarts containers even after manual stop. This can interfere with maintenance windows.

How to avoid: Use unless-stopped for services that should run until intentionally stopped. Use always only when you always want the container running, even after a daemon restart and regardless of manual stops.

4. Getting stuck with on-failure retries

Why it happens: Setting on-failure:10 on a container that has a persistent error results in 10 restarts and then the container stops. If no one notices, the service remains down.

How to avoid: Combine on-failure with alerting. Monitor container status and send notifications when a container enters a stopped state after retries. Consider using unless-stopped with a healthcheck for self-healing.

Conclusion

Docker restart policies are a key part of container resilience, but they must be configured with capacity planning in mind. Without limits, containers can consume excessive resources and cause host instability. Without proper policies, a broken container may loop indefinitely or fail silently.

By following the practices in this article—establishing a baseline, choosing the right restart policy, setting resource limits, verifying behavior, and planning for recovery—you can maintain a stable and efficient container environment.

As a next step, pick one container in your environment, review its restart policy and resource limits, and run a failure simulation. Document the results and share with your team. Make this a regular review process to catch issues before they cause downtime.

Remember: a reliable workflow makes failure visible, protects sensitive values, limits changes, and defines recovery verification ahead of time.

Now it is your turn: use the checklists, commands, and examples to harden your containers.

Related Research

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL