Container States in Docker: The Life Story of Every Container
A complete, beginner-friendly guide to every stage a Docker container passes through, how it moves between them, and what each stage actually means for your data and your application.
Think about a parcel moving through a delivery network. It’s ordered, then packed, then in transit, then delivered, and maybe eventually returned. At any given moment, that parcel is in exactly one of these stages, and knowing which one tells you exactly what’s happening to it and what might happen next. A Docker container has a very similar life story, made up of a small, well-defined set of states. This guide walks through every one of them, what causes a container to move from one to the next, and why understanding this “life story” makes troubleshooting Docker dramatically easier.
1What Is a Container State?
Before listing the states themselves, let’s understand what the word actually describes.
A container’s state is a short label describing what that specific container is doing right now — whether its main process is actively running, has finished, is temporarily frozen, or has never been started at all. Every container that exists on your machine is always in exactly one state at any given moment, and Docker tracks this state internally, updating it automatically the moment something changes.
Think of a container’s state like the status shown on a food delivery app: “Order Placed,” “Preparing,” “Out for Delivery,” “Delivered.” At any moment your order is in exactly one of these stages, and that single label tells you a great deal about what’s already happened and what to expect next. A container’s state works exactly the same way.
Understanding states matters because the exact same command can behave completely differently depending on which state a container is currently in. Trying to stop a container that’s already stopped does nothing meaningful. Trying to start a container that’s currently running produces an error. Recognizing a container’s current state is often the very first step in correctly diagnosing why something isn’t behaving the way you expect.
A Snapshot Label
A short description of exactly what a container is doing at this specific moment.
A Change of State
The moment a container moves from one state to another, triggered by a command or an internal event.
What States Track
The single primary program running inside the container, whose activity largely determines the container’s overall state.
The Final Report
A small number left behind describing how the container’s process finished, once it has stopped.
2The Core States, One by One
Docker recognizes a small, fixed set of states — here’s what each one actually means.
Created
The container exists — its filesystem has been prepared from its image, and all its settings are locked in — but its main process has never actually been launched yet. It’s ready and waiting, like a car sitting in the driveway with the engine off.
Running
The main process is actively executing. The container can respond to requests, write files, use memory and processing power, and generally be doing real work.
Paused
The main process is frozen in place, still fully loaded in memory, but not currently being given any processing time at all. Nothing about it advances until it’s unpaused.
Exited (Stopped)
The main process has finished running, either because it completed its work naturally, crashed, or was told to shut down. The container itself still exists, with its filesystem intact, ready to be started again.
Restarting
A brief, transitional state where Docker is in the middle of automatically restarting a container, usually because of a restart policy responding to a crash.
Dead
A rare, unusual state where Docker was unable to fully stop or clean up the container properly, leaving it in a broken condition that typically requires removing the container outright to resolve.
3The Full Life Cycle, From Creation to Removal
Seeing all the states together, and how they connect, makes the whole picture click into place.
stateDiagram-v2
[*] --> Created: container created
Created --> Running: start
Running --> Paused: pause
Paused --> Running: unpause
Running --> Exited: stop / process ends
Exited --> Running: start
Running --> Restarting: crash with restart policy
Restarting --> Running: restart completes
Exited --> [*]: remove
Running --> Dead: failed cleanup
Dead --> [*]: remove
Notice that most arrows in this diagram point both ways — a container can cycle between running and exited, or between running and paused, many times over its lifetime, without ever needing to be removed and recreated. The only truly final, one-way step is removal, which is covered in Chapter 7, since it’s fundamentally different from every other state transition on this diagram.
4Created but Never Started
A subtle, often-overlooked state that isn’t quite the same as anything else.
It’s entirely possible to create a container without immediately starting it, leaving it sitting in the created state indefinitely. In this state, the container’s filesystem has already been fully prepared from its image, and all of its configuration is fixed and ready, but its main process has genuinely never run even once, meaning it hasn’t done any work, written any of its own new data, or consumed any meaningful processing resources yet.
A container in the created state is a useful moment to inspect exactly how a container would be configured before it actually runs, since all of its settings are already locked in but no process has executed yet to potentially change anything.
Most day-to-day usage skips straight past this state, since the common action that starts a fresh container also implicitly creates it in the same step. But recognizing that “created” and “running” are genuinely two separate, distinct states — not just two names for the same thing — helps explain occasional situations where a container appears to exist but has seemingly never produced any output or logs.
5Running vs. Paused
Two active-sounding states that behave very differently underneath.
A running container’s main process is genuinely executing, actively using the processor, potentially responding to network requests, and free to read or write files at any moment. A paused container’s main process, by contrast, is still fully loaded in memory — nothing about it has been shut down — but it has been suspended by the operating system so that it simply isn’t given any opportunity to execute at all, as though time itself had stopped for that one process.
| Aspect | Running | Paused |
|---|---|---|
| Process in Memory | Yes, active | Yes, but frozen |
| Using Processing Power | Yes, as needed | No, none at all |
| Can Respond to Requests | Yes | No, requests simply wait |
| Resuming | Not applicable | Instant, with nothing lost |
Because a paused process was never actually terminated, unpausing it is instant and loses absolutely nothing — no in-progress work, no memory state, nothing. This is a meaningfully different guarantee than moving from the exited state back to running, since exiting does genuinely terminate the process, as explained further in Chapter 6.
6Understanding the Exited State and Exit Codes
A container doesn’t just “stop” — it leaves behind a small clue explaining why.
Once a container’s main process has finished, for any reason, the container moves into the exited state, and Docker records a small number alongside it called an exit code. This number is a widely used convention for describing how a process finished — whether it completed successfully, or ran into some kind of problem along the way.
Clean Success
The process finished its work and exited entirely normally, with no errors reported.
Something Went Wrong
The process exited because of an error condition it detected internally, with the specific number often hinting at the type of problem.
Forcefully Terminated
A strong signal that the process was killed forcefully rather than shutting down on its own, often due to running out of allowed memory or being explicitly killed.
Reading a container’s exit code is often the fastest first step in figuring out why something stopped unexpectedly, long before digging through detailed logs — a clean zero suggests everything is fine, while a non-zero code is an immediate signal that something worth investigating happened.
7Removal: The One True Ending
Every other state is reversible. This one isn’t.
As the life cycle diagram in Chapter 3 shows, nearly every state a container can be in leads back to another reachable state — a running container can be stopped and started again indefinitely, a paused container can always be unpaused. Removal is fundamentally different: it’s the genuine, permanent end of a container’s story. Once removed, the container’s own filesystem and identity are erased for good, and there is no state to return to afterward.
It’s easy to confuse “stopped” with “gone” precisely because both sound like an ending. As covered throughout this guide, a stopped (exited) container is very much still present and can be started again at any time; a removed container is genuinely, permanently deleted, along with anything that was only ever stored in its own internal filesystem rather than in a separate volume or bind mount.
A container typically must be stopped before it can be removed, which is why “stopped” and “removed” often get mentally grouped together as though they were one and the same action, even though they represent two very different states with two very different levels of permanence.
8The Restarting State and Restart Policies
Some containers are configured to bounce back on their own the moment they fail.
As discussed in Chapter 2, “restarting” is a brief, transitional state, not a place a container sits indefinitely. It appears when a container has a restart policy attached, and that policy has decided the container should be automatically brought back after exiting — usually because it crashed rather than shutting down deliberately.
flowchart LR
A["Running"] -->|"process crashes"| B["Exited"]
B -->|"restart policy applies"| C["Restarting"]
C --> D["Running again"]
style A fill:#fafafa,stroke:#171717
style D fill:#fef2f2,stroke:#dc2626
Without a restart policy configured, a crashed container simply stays in the exited state until a person manually starts it again. With one configured, this entire cycle can happen automatically and repeatedly, which is enormously useful for keeping important services available, but can also mask a genuine, ongoing problem if a container keeps crashing and silently restarting over and over without anyone noticing.
9Health Status: A Layer on Top of “Running”
A container can be technically running while still not actually working correctly.
It’s entirely possible for a container’s main process to be running — using memory, staying alive, never crashing — while the application inside it is completely broken in some other way, such as being unable to connect to a database it depends on. To catch situations like this, Docker supports an optional health check, a small, repeated test that determines whether the application inside a running container is genuinely working properly, not just merely alive.
| Health Status | What It Means |
|---|---|
| Starting | The container is running, but its very first health check hasn’t completed yet |
| Healthy | Recent health checks have passed; the application seems to be working correctly |
| Unhealthy | Recent health checks have failed; the container is running, but something is genuinely wrong |
Health status exists alongside a container’s main state, not instead of it — a container can simultaneously be in the “running” state while also being reported as “unhealthy,” which is an important, more specific signal than the main state alone would ever provide.
10Best Practices and a Common Anti-Pattern
A short checklist for using container states effectively when diagnosing problems.
Check a container’s state first, before anything else
Many confusing situations are explained the moment you know whether a container is actually running, exited, or paused.
Always look at the exit code after an unexpected stop
As covered in Chapter 6, the exit code is often the fastest clue toward understanding what actually happened.
Don’t confuse exited with removed
An exited container is fully recoverable; a removed one, as explained in Chapter 7, genuinely is not.
Add health checks to anything where “running” isn’t enough
For applications where being alive doesn’t guarantee working correctly, health status gives a much more meaningful signal.
Problem
A team configures an aggressive restart policy on a service, sees it stay “running” most of the time, and assumes everything is healthy — without ever checking whether it’s quietly crashing and restarting every few minutes.
Why It’s Harmful
As discussed in Chapter 8, an automatic restart can mask a real, ongoing failure by repeatedly returning the container to the running state, giving a false sense that nothing is wrong while the underlying problem never actually gets investigated or fixed.
Correct Approach
Monitor for repeated restarts specifically, not just the current state, and pair restart policies with health checks and logging so a container that’s crash-looping is noticed quickly rather than silently tolerated.
11Real-World and Industry Examples
Understanding container states shows up constantly in everyday operational work, across many kinds of teams.
Automated Alerts
Monitoring systems watch for containers repeatedly cycling through the restarting state, treating a crash loop as an early warning sign worth investigating.
First-Line Diagnosis
Checking a container’s current state and its most recent exit code is often the very first troubleshooting step when a user reports something isn’t working.
Health-Aware Traffic Routing
Traffic is only routed to containers reporting a healthy status, as described in Chapter 9, keeping users away from instances that are technically running but functionally broken.
Everyday Pausing
Developers pause resource-hungry containers they aren’t actively using, resuming them instantly later without losing any in-progress state.
12Frequently Asked Questions
No. As explained in Chapter 7, an exited container still exists and can be started again; a removed container is genuinely and permanently deleted.
Yes. As covered in Chapter 9, health status is a separate signal layered on top of the running state, describing whether the application inside is actually working correctly, not just whether the process is alive.
As discussed in Chapter 5, pausing freezes the process without terminating it, allowing an instant, lossless resume, while stopping genuinely ends the process, as explored throughout this guide.
As explained in Chapter 6, it means the process finished on its own, entirely normally, with no reported error.
This is a crash loop, described in Chapter 8 — the container’s process is repeatedly failing shortly after starting, and its restart policy keeps bringing it back automatically each time.
No — as noted in Chapter 2, it’s a rare state indicating Docker couldn’t properly clean up the container, and it typically requires removing that container to resolve.
13Summary and Key Takeaways
Every Docker container moves through a small, well-defined set of states across its lifetime — created, running, paused, exited, occasionally restarting, and eventually, permanently, removed. Recognizing which state a container is currently in, understanding what caused it to get there, and knowing what each state does and doesn’t preserve turns confusing, mysterious behavior into something predictable and explainable. States are one of the most fundamental, everyday concepts in working with Docker, underlying nearly every other action you’ll take with a container.
Key Takeaways
- A container is always in exactly one state — a short label describing exactly what it’s doing right now.
- Most transitions are reversible — running, paused, and exited can be cycled between repeatedly without recreating the container.
- Removal is the one true, permanent ending — unlike every other state, there’s no going back from it.
- Pausing freezes; stopping terminates — pausing loses nothing and resumes instantly, while stopping genuinely ends the process.
- Exit codes explain how a container stopped — a quick, valuable first clue when something goes wrong.
- Restart policies can mask repeated crashes — a crash loop can look like “running” at a glance without real monitoring.
- Health status is more specific than “running” — a container can be alive yet not actually working correctly.