Restart Policies in Docker: An In-Depth Look

Restart Policies in Docker: An In-Depth Look

A deep, beginner-friendly guide that goes beyond the basics — exploring exactly how Docker's automatic recovery mechanism thinks, where it interacts with other systems, and where it quietly runs into its own limits.

Imagine an automatic sprinkler system in a garden. A simple version just turns on at a set time each day. A genuinely well-designed one, though, understands more nuance: it knows not to water again if it just rained, it knows to stop trying if a pipe is clearly broken rather than flooding the garden forever, and it knows the difference between “the hose disconnected by accident” and “someone deliberately turned the system off for the season.” Docker’s restart policies, on the surface, look like that simple timer-based sprinkler — a basic rule for bringing a container back after it stops. But underneath, there’s considerably more nuance worth understanding: how retries actually behave over time, how policies interact with the rest of the system, and where this mechanism’s real boundaries lie. This guide goes past the fundamentals into exactly that depth.

1A Fast Recap of the Fundamentals

A brief refresher to establish shared footing before going deeper.

A restart policy is a rule, attached to a container when it’s created, telling Docker exactly what to do the moment that container stops — whether to leave it stopped, or to automatically start it again. Docker offers four options: never restarting automatically at all, restarting only after a genuine failure, restarting under essentially any circumstance, and restarting under any circumstance except when a human deliberately stopped it.

No

Never Restart

The container stays stopped after it exits, no matter why it stopped.

On-Failure

Restart Only on Error

Restarted only if the exit code indicates something went wrong, not if it exited cleanly.

Always

Always Restart

Restarted regardless of the reason, even overriding a manual stop after a host reboot.

Unless-Stopped

Restart Unless Manually Stopped

Restarted like “always,” except a deliberate manual stop is respected and remembered across a host reboot.

i
Where This Guide Goes Further

With that foundation in place, the rest of this guide focuses on the mechanics beneath these four simple labels — the timing, the internal state tracking, and the situations where restart policies alone genuinely aren’t enough.

2The Restart Policy Is Stored, Not Just Applied Once

An important nuance about where this rule actually lives and how long it persists.

A restart policy isn’t a one-time instruction that Docker glances at only the moment a container first starts. It’s stored as a permanent part of that specific container’s own configuration, checked fresh every single time that container stops, for as long as the container itself continues to exist. This means a container that has already restarted automatically ten times will still be evaluated against that exact same policy an eleventh time, and a twelfth, indefinitely, until either the container is removed or its policy is explicitly changed.

flowchart TD
    A[Container Created With a Restart Policy] --> B[Policy Stored in Container's Own Configuration]
    B --> C[Container Stops]
    C --> D[Docker Reads the Stored Policy]
    D --> E[Decision Made: Restart or Leave Stopped]
    E --> F{Container Restarted?}
    F -- Yes --> C
    F -- No --> G[Container Remains Stopped Until Manual Action]
        
FIG 1 — The restart policy is re-evaluated every single time the container stops, not just once at the very beginning.
Simple Analogy

Think of it like a standing instruction left with a house sitter, not a one-time favor. “Every time the smoke alarm battery dies, replace it” is a rule that applies indefinitely, every single time that situation recurs — not just the first time it happens.

3The Restart Count and Why It Matters

A piece of internal state Docker keeps that has real practical significance.

For each container, Docker internally tracks how many times it has been automatically restarted due to its restart policy. This number isn’t just trivia — it’s directly used by the “on-failure” policy’s optional retry limit, and it’s also one of the single most valuable pieces of information a person can check when trying to understand whether a container is genuinely healthy or quietly struggling in a loop.

!
A Subtle but Important Distinction

This restart count reflects restarts caused specifically by the restart policy itself — not every single time a container has ever been started throughout its entire history, including manual starts. Understanding exactly what this number does and doesn’t include avoids drawing the wrong conclusion from it.

4The Real Shape of the Backoff Delay

Going beneath the simple statement “there’s a delay between retries” to understand its actual behavior.

When a container using the “on-failure” or “always”-style policies keeps crashing repeatedly, Docker doesn’t retry at a fixed, constant interval. It begins with a very short delay after the first failure, and that delay grows progressively longer with each additional consecutive failure — a pattern generally referred to as exponential backoff. This means the very first retry after a crash happens almost immediately, while the tenth consecutive retry might be separated from the ninth by a delay of many seconds or more.

sequenceDiagram
    participant D as Docker Engine
    participant C as Crashing Container
    D->>C: Attempt 1 (near-instant delay)
    C-->>D: Fails
    D->>C: Attempt 2 (short delay)
    C-->>D: Fails
    D->>C: Attempt 3 (longer delay)
    C-->>D: Fails
    D->>C: Attempt 4 (even longer delay)
    Note over D: Delay keeps growing with each consecutive failure
        
FIG 2 — The growing delay pattern between consecutive restart attempts, rather than a fixed, constant interval.
Simple Analogy

It’s similar to how a person might handle a car that won’t start: try again immediately once, then wait a minute and try again, then wait several minutes before the next attempt, rather than turning the key over and over again with no pause at all, which would likely just drain the battery faster.

i
Why This Design Choice Matters

This growing delay directly protects the host system from being overwhelmed by an extremely rapid, tight restart loop, and it also gives any temporary underlying issue — a dependency that’s briefly unavailable, for instance — meaningfully more time to resolve itself between attempts as the failures continue.

5What Counts as “Failure” Beyond a Simple Crash

Broadening the definition of failure beyond the obvious case.

It’s easy to think of “failure” purely in terms of an application crashing with an obvious error. But the exit-code mechanism that “on-failure” relies on is more general than that — it captures any situation where the container’s main process exits with a non-zero code, which can include far subtler situations: a process that couldn’t find a required configuration value and deliberately exits rather than running incorrectly, or a startup routine that intentionally fails fast because a dependency it needs isn’t ready yet.

Obvious Failure

Unhandled Crash

The application encounters an unexpected error it has no way to gracefully handle, and the process terminates abnormally.

Deliberate Failure

Intentional Early Exit

The application detects a problem — like missing required configuration — and deliberately exits with a non-zero code rather than continuing in a broken state.

Dependency Failure

Startup-Time Dependency Check

The application checks for a required dependency, like a database, at startup, and exits if that dependency isn’t yet reachable, expecting the restart policy to naturally retry once conditions improve.

i
A Genuinely Useful Pattern

That last case — an application deliberately exiting when a dependency isn’t ready — is actually a legitimate, common design pattern. It effectively delegates the “keep trying until the dependency becomes available” logic to the restart policy itself, rather than building that retry logic separately inside the application.

6Restart Policies and Health Checks: A Deeper Relationship

Exploring how restart policies interact with a completely separate, but related, mechanism.

Docker supports a separate concept called a health check — a way for a container to periodically report whether it’s not just running, but genuinely healthy and functioning correctly, independent of whether its main process has actually exited. A container can be technically “running” from the restart policy’s point of view, while simultaneously being reported as “unhealthy” by its health check — these are two distinct, related-but-separate signals.

flowchart TD
    A[Container's Main Process] --> B{Is the process still running?}
    B -- No --> C[Restart Policy Decides What Happens Next]
    B -- Yes --> D{Does the Health Check Pass?}
    D -- Yes --> E[Reported as Healthy]
    D -- No --> F[Reported as Unhealthy, But Still Running]
        
FIG 3 — Restart policies react to the process stopping entirely; health checks report on ongoing wellness of a process that’s still technically running.
!
A Genuine Gap Worth Understanding

A restart policy alone does not automatically restart a container purely because its health check is failing. If an application’s process is technically still alive but stuck, deadlocked, or otherwise unable to serve requests, the restart policy has nothing to react to on its own, since nothing has actually stopped.

To bridge this gap, many real systems configure the application itself to exit deliberately when it detects it’s in a genuinely unhealthy, unrecoverable state — turning an “unhealthy but technically alive” situation into an actual process exit, which the restart policy can then properly react to.

7The Retry Limit: A Feature Specific to “On-Failure”

Understanding a capability that only exists for one specific policy, and why that design makes sense.

Only the “on-failure” restart policy supports an explicitly configurable maximum retry count — a hard ceiling on how many times Docker will attempt to restart before giving up entirely and leaving the container stopped. Neither “always” nor “unless-stopped” offer this same built-in cap; both are designed around the philosophy that a container meant to run indefinitely should keep being retried indefinitely, since giving up entirely would mean a service meant to be permanently available becomes permanently unavailable instead.

PolicySupports a Retry LimitUnderlying Philosophy
On-FailureYes, optional and configurableA task expected to eventually succeed or genuinely give up
AlwaysNoA permanent service that should never simply give up
Unless-StoppedNoSame as “always,” but respecting an explicit manual stop
Simple Analogy

A retry limit makes sense for a delivery driver trying to reach someone by phone a reasonable number of times before giving up and trying a different approach. It makes far less sense for a hospital’s emergency generator, which should keep trying to restart indefinitely after a failure, since giving up isn’t an acceptable outcome for something that critical.

8What Happens When the Retry Limit Is Reached

A specific, important edge case worth understanding clearly.

Once a container configured with “on-failure” and a maximum retry count has exhausted that limit without a single successful, sustained run, Docker stops attempting to restart it and leaves it in a stopped state. Crucially, this doesn’t remove the container, and it doesn’t change its stored restart policy — it simply means Docker has, for now, given up on automatic recovery, and the container will sit stopped until a person intervenes.

i
Key Idea

A container that has hit its retry limit is a strong, unambiguous signal that something is genuinely broken and needs direct human attention — it’s meaningfully different from a container that’s merely restarted once or twice and then stabilized successfully.

9Restart Policies Across a Host Reboot

A deeper look at exactly how these policies behave when the entire underlying machine restarts.

When the host machine itself reboots, the Docker Engine, once it comes back up, reviews every container it’s still tracking and checks each one’s restart policy to decide whether it should be automatically started again as part of that boot process. This is what allows “always” and “unless-stopped” containers to come back to life without any human action, even after the entire machine has been powered off and back on.

flowchart TD
    A[Host Machine Reboots] --> B[Docker Engine Starts Back Up]
    B --> C[Engine Reviews Every Tracked Container]
    C --> D{What was the container's restart policy?}
    D -- No or On-Failure with clean history --> E[Leave Stopped]
    D -- Always --> F[Start Automatically]
    D -- Unless-Stopped, wasn't manually stopped --> F
    D -- Unless-Stopped, was manually stopped --> E
        
FIG 4 — How Docker decides which containers to bring back automatically after the entire host machine restarts.
i
Practical Implication

This is precisely why “always” and “unless-stopped” are the policies of choice for genuinely critical, long-running services — a planned maintenance reboot of the host machine doesn’t require anyone to remember to manually restart every important container afterward.

10Restart Policies vs Orchestration-Level Recovery

Understanding where this single-host mechanism fits relative to larger, multi-host systems.

Restart policies operate entirely within the scope of a single Docker Engine on a single host machine. Larger orchestration systems, designed to manage containers across many machines working together, typically implement their own, more sophisticated recovery logic — one that can, for example, decide to relaunch a failed container on a completely different, healthy machine, rather than being limited to simply retrying it on the same host where it originally failed.

AspectDocker Restart PolicyOrchestration-Level Recovery
ScopeA single host machinePotentially many machines working together
Can relocate a failed workload elsewhereNoOften, yes
Awareness of overall cluster healthNoneTypically built in
Complexity to set upMinimal, built directly into every containerRequires a separate, more complex system
Simple Analogy

A restart policy is like a single employee who, if they trip and fall, gets back up and keeps working at their same desk. Orchestration-level recovery is more like a manager who notices an entire desk has become unusable and reassigns that person’s work to a different desk entirely, somewhere else in the building.

11The Limits of What a Restart Policy Actually Solves

Being honest and precise about where this mechanism’s usefulness genuinely ends.

Doesn’t Fix Root Causes

Symptom, Not Cause, Recovery

A restart policy reacts to a process stopping — it has no understanding of, and no ability to fix, whatever underlying bug or misconfiguration actually caused that stop in the first place.

Doesn’t Cover Silent Hangs

A Frozen but Still-Running Process

A process that’s technically still running, but stuck and unresponsive, gives the restart policy nothing to react to, since nothing has actually stopped from its point of view.

Doesn’t Relocate Workloads

Bound to a Single Host

If the entire host machine itself is genuinely unavailable — not just rebooting, but truly down — a restart policy alone offers no path to running that workload somewhere else instead.

Doesn’t Alert Anyone

Silent by Default

Automatic restarts happen quietly, on their own, with no built-in notification to a human unless a separate monitoring system is specifically watching for repeated restarts.

Weighing the deeper, nuanced value of restart policies against their genuine, specific limits.

Advantages

  • Provides automatic, immediate recovery from crashes with essentially zero configuration overhead
  • The growing backoff delay protects the host from being overwhelmed by a tight, rapid crash loop
  • Works consistently across host reboots, keeping critical services available without manual intervention
  • Composes naturally with an application’s own deliberate-exit-on-dependency-failure pattern
  • Requires no separate infrastructure — the mechanism lives entirely within the Docker Engine itself

Disadvantages / Trade-offs

  • Has no awareness of a container that’s technically running but genuinely unhealthy, unless the application itself is designed to exit in that case
  • Is entirely bound to a single host, offering no way to relocate a workload if the host itself becomes unavailable
  • Provides no built-in alerting, meaning a repeatedly crashing container can go unnoticed without separate monitoring
  • Cannot diagnose or fix whatever underlying issue is actually causing the failures in the first place

13Best Practices and Common Mistakes

More advanced habits, going beyond the basics, for teams relying on restart policies in real systems.

i
Best Practice

For applications where “technically running but unhealthy” is a real risk, design the application to detect that state itself and deliberately exit, effectively converting a gap that restart policies can’t see into a signal they can directly react to.

!
Common Mistake

Treating a low restart count as automatic proof that everything is fine, without considering that a container could be quietly unhealthy in ways the restart policy has no visibility into at all.

!
Common Mistake

Relying purely on a restart policy for a genuinely multi-host, high-availability system, when orchestration-level recovery is actually needed to handle the case of an entire host becoming unavailable.

i
Best Practice

Pair restart policies with active alerting on restart counts, so repeated automatic recoveries — which are silent by default — actually reach a human’s attention rather than being invisibly absorbed by the system indefinitely.

14Design Patterns and Anti-Patterns

More advanced patterns for structuring how a system relies on automatic restart behavior.

ANTI-PATTERN-01 Avoid
Problem

Building an application that can become stuck in an unresponsive, hung state without ever actually exiting, while relying entirely on a restart policy to eventually recover it.

Why It’s Harmful

Since nothing has actually stopped from the restart policy’s perspective, it has no trigger to act on at all — the application can remain stuck indefinitely, technically “running” but completely unable to serve its purpose, with no automatic recovery ever kicking in.

Correct Approach

Combine a restart policy with a health check and application-level logic that deliberately exits once a genuinely unrecoverable, unhealthy state is detected, giving the restart policy an actual event to react to.

PATTERN-01 Recommended
Problem

An application needs to wait for a dependency, like a database, to become available at startup, without writing custom retry logic inside the application itself.

Why It’s Harmful

N/A — this describes the recommended solution rather than a problem to avoid.

Correct Approach

Have the application check for the dependency once at startup and exit immediately with a failure code if it isn’t ready, relying on an “on-failure” restart policy — with a reasonable retry limit — to naturally retry the entire startup sequence with the built-in growing delay, until the dependency finally becomes available.

15Monitoring and Deeper Observability

Going beyond a simple glance at whether a container is currently running.

Genuinely useful monitoring around restart policies looks past the simple “is it running right now” question, and instead tracks the restart count over time, the pattern of how frequently restarts are happening, and — where health checks are configured — how the health status correlates with those restarts. A container that restarted once, weeks ago, and has been stable ever since tells a very different story than one that has restarted five times in the last hour, even though both might currently show as “running.”

4
Restart Policy Options
Growing
Backoff Delay Pattern
Host-Scoped
Not Cluster-Aware
i
Tip

Treating a rising restart count as a genuine alerting signal, not just a passive data point, closes much of the visibility gap that restart policies leave open on their own — turning silent, automatic recoveries into something a team actually notices and can act on.

16Security Considerations

A closer, more nuanced look at the security implications of automatic restart behavior.

Masking Exploitation

Repeated Crashes From an Attack

If a vulnerability causes a crash when triggered, aggressive automatic restarting can keep the service available across repeated exploitation attempts, potentially without anyone noticing the pattern unless restart activity is actively monitored.

Resource Pressure

A Restart Loop as an Indirect Denial-of-Service Risk

A container stuck in a rapid restart loop consumes real CPU and I/O on the host repeatedly, and at scale, this can meaningfully degrade the performance of other, unrelated containers sharing that same machine.

False Confidence

Mistaking “Running” for “Secure”

A service that keeps coming back up after every crash can create a false sense that everything is fine, when in reality it may be repeatedly failing due to a genuine, unaddressed security issue that deserves direct investigation.

17Real-World and Industry Examples

How these deeper mechanics show up in real, production-grade systems.

Startup-Order Dependency Handling

Teams running a database alongside an application that depends on it commonly rely on the application’s deliberate-exit-on-missing-dependency pattern, combined with an “on-failure” policy, to naturally handle startup ordering without complex, custom coordination logic.

Small Self-Managed Production Systems

Teams without a full orchestration platform frequently lean heavily on “unless-stopped” combined with active restart-count monitoring, treating this combination as their primary, practical line of defense against unattended downtime.

Systems Layered Beneath Orchestration

Even within larger orchestrated environments, individual container-level restart behavior often still plays a supporting role beneath the orchestration system’s own, broader recovery logic, handling the fast, local case while orchestration handles the larger, cluster-wide case.

Long-Running Background Workers With Health Checks

Worker processes that can silently get stuck without crashing outright are often built to actively self-check their own health and deliberately exit if something is clearly wrong, specifically to give their restart policy something concrete to act on.

18Frequently Asked Questions

Q1Does the backoff delay ever reset back to being short again?

Generally, once a container has run successfully and stayed up for a meaningful, sustained period, a subsequent failure is treated as a fresh occurrence, and the delay pattern effectively starts over from its short, initial value again.

Q2Can a restart policy detect that a container is stuck, even though its process is technically still running?

No — a restart policy only reacts to the main process actually exiting. A stuck but still-running process requires a separate mechanism, like a health check combined with application-level logic, to actually convert that stuck state into a process exit the restart policy can respond to.

Q3Is the restart count reset if I manually restart a container myself?

The restart count specifically reflects automatic restarts triggered by the policy itself; a manual restart initiated directly by a person is a separate action, and its effect on that stored count can depend on the specific circumstances of how and why the container had stopped beforehand.

Q4If I change a container’s restart policy, does that affect its restart history?

Changing the policy affects how future stops are handled going forward — it doesn’t retroactively alter what has already happened in the past under the previous policy.

Q5Can restart policies alone provide true high availability for a critical service?

On their own, no — they provide solid, automatic recovery within a single host, but true high availability, especially the ability to survive an entire host becoming unavailable, generally requires an orchestration-level system layered on top.

Q6Does a restart policy have any awareness of why a container originally crashed?

Only in the limited sense of the exit code — whether it indicated success or failure. It has no deeper insight into the actual underlying cause, and it makes no attempt to diagnose or address that cause itself.

19Summary and Key Takeaways

Beneath their simple, four-option surface, Docker’s restart policies carry real, worthwhile depth: a stored, permanently re-evaluated rule, a tracked restart count, a deliberately growing backoff delay designed to protect the host, and a meaningful, specific boundary around what they can and cannot actually detect or fix. Understanding that restart policies react only to a process genuinely exiting — not to a process that’s merely unhealthy or stuck — reveals exactly why they pair so well with health checks and deliberate, application-level exit behavior. And recognizing that they operate entirely within a single host explains precisely why larger, multi-host systems need a more sophisticated, orchestration-level layer of recovery on top. Used with this deeper understanding, restart policies become a precise, well-calibrated tool rather than a vague, general-purpose safety net.

Key Takeaways

  • The policy is stored permanently on the container — re-evaluated every single time it stops, not just once at the beginning.
  • Backoff delay grows with each consecutive failure — protecting the host from a tight, rapid crash loop rather than retrying at a fixed pace.
  • Only “on-failure” supports a retry limit — reflecting a deliberate design distinction between tasks meant to eventually give up and services meant to run forever.
  • Restart policies can’t see a “stuck but running” process — that gap is closed by combining them with health checks and deliberate application-level exits.
  • They’re bound to a single host — larger, multi-host recovery genuinely requires an orchestration-level system layered on top.
  • Restart activity is silent by default — active monitoring of restart counts is what turns automatic recovery into something a team actually notices.
  • They fix the symptom, never the cause — a repeatedly restarting container is a strong, clear signal that deserves direct human investigation, not just quiet tolerance.