Name the states a Docker container can be in and describe what moves it between them, including what the `dead` state means.
answer
- created / running / paused / restarting / removing / exited / dead
- exited ≠ removed — rm frees the writable layer
- pause = freezer cgroup, no signal, memory kept
- dead = teardown failed, needs rm -f
- inspect .State.Status; docker events for transitions
basics
~20 screated, running, paused, restarting, removing, exited, dead. run/start move created or exited to running; stop/kill or the process ending move running to exited; pause/unpause toggle paused; rm moves through removing to gone. dead means partial removal failed and the container is unusable.
solid answer
~50 sDocker reports a container's status in `docker ps -a` and in `docker inspect -f '{{.State.Status}}'`. The states are: - **created** — configured by `docker create` but never executed. - **running** — the entrypoint process is alive. Entered via `docker run`/`docker start`/`docker unpause`/a restart-policy restart. - **paused** — all processes frozen by the kernel's freezer cgroup via `docker pause`; memory intact, nothing scheduled. `docker unpause` resumes. - **restarting** — the daemon is bringing it back up under its restart policy. - **removing** — `docker rm` is tearing it down. - **exited** — the main process ended (cleanly, by signal, or via `docker stop`/`kill`); the writable layer and the container object still exist, so it can be started again or inspected. - **dead** — removal or teardown partially failed, typically from a wedged mount or storage-driver error; the container cannot be started and usually needs `docker rm -f`. The practical points: exited is not the same as removed, and only `docker rm` reclaims the writable layer.
code
bash · 3 linesdocker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.Error}}' api
docker ps -a --format 'table {{.Names}}\t{{.Status}}'
docker events --filter container=apigo deeper
List the states and the commands that move between them, and be clear that exited is not the same as removed.
Add the mechanics — the freezer cgroup behind pause, restarting as a restart-policy artifact, dead as a failed teardown — and read state from docker inspect rather than the ps text.
Use docker events and .State fields to diagnose fast flapping and stuck teardown, and know the recovery path for dead containers.
Care about the operational consequences: disk reclamation policy for exited containers, alerting on containers stuck in restarting or dead, and keeping hosts free of manual state.
## Where the states live Docker exposes the state in two places. `docker ps -a` shows a human STATUS column ("Up 3 minutes", "Exited (137) 2 hours ago", "Created", "Paused"). The machine-readable truth is in `docker inspect`: ``` docker inspect -f '{{.State.Status}} {{.State.Running}} {{.State.ExitCode}} {{.State.StartedAt}} {{.State.FinishedAt}}' c ``` `.State.Status` is one of: `created`, `running`, `paused`, `restarting`, `removing`, `exited`, `dead`. ## The states **created** — the container object exists: writable layer allocated, configuration recorded (command, env, mounts, ports, network), but the entrypoint has never run. It occupies disk and a name. `docker ps` hides it; `docker ps -a` shows it. **running** — the entrypoint process is alive in its namespaces. Reached from `created` or `exited` via `docker start`, from `paused` via `docker unpause`, from `restarting` when the daemon restarts it, or directly via `docker run`. **paused** — every process in the container is frozen by the kernel freezer cgroup. Memory is retained, the processes are not scheduled, and no signal-based negotiation happened. `docker unpause` resumes exactly where things were. Note pausing is not a lifecycle event from the application's perspective — it never knows. **restarting** — a transient state while the daemon applies a restart policy after an exit. You will catch a crash-looping container here between attempts. **removing** — a transient state during `docker rm` while the writable layer, network endpoints and metadata are torn down. **exited** — the main process has terminated, for any reason: it returned from main, it was signalled by `docker stop`/`docker kill`, it crashed, or the kernel OOM-killed it. The container object survives: the writable layer, the logs, the configuration and the recorded exit code all remain, which is precisely what makes post-mortem work possible (`docker logs`, `docker inspect`, `docker cp` out of it). It can be started again with `docker start` — same filesystem, fresh process. **dead** — the odd one out. It is not a normal step in the lifecycle; it means the daemon tried to remove or tear down the container and could not complete the operation, usually because a resource is stuck: an unmountable filesystem, a busy mount point, a storage-driver or overlayfs error, or the daemon dying mid-removal. A dead container cannot be started. The remedy is `docker rm -f <id>`; if that also fails, the underlying mount or storage problem must be cleared first, sometimes with a daemon restart. ## Transitions worth memorizing ``` (image) --create--> created --start--> running --stop/kill/exit--> exited \--pause--> paused --unpause--> running exited --start--> running exited/created --rm--> removing --> (gone) running --restart policy--> restarting --> running any --failed teardown--> dead ``` `docker restart` is stop + start on the **same** container: same ID, same name, same writable layer, new process. It is not a replacement. ## Two distinctions candidates blur **exited vs removed.** An exited container still consumes disk for its writable layer and its logs, still holds its name (so `docker run --name api ...` will refuse to reuse it), and still shows in `docker ps -a`. Only `docker rm` frees all of that. Machines accumulating hundreds of exited containers is the most common form of "Docker ate my disk". **paused vs stopped.** Pausing freezes processes in place with memory intact and no signals involved; the application cannot react and does not know time passed. Stopping sends a signal, the process shuts down and its memory is released. Anything holding a network connection open across a pause will find peers timing out, because the clock keeps running even though the processes do not. ## Practical inspection ``` docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}' docker ps -a --filter status=exited --filter status=dead docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.Error}}' c docker events --filter container=c ``` `docker events` is the underused one: it streams lifecycle transitions (create, start, die, stop, pause, unpause, destroy, oom) as they happen, which is how you catch a container that flips through states too fast for `docker ps` to show.
- What is the practical difference between an exited container and a removed one?An exited container still exists as an object: its writable layer, logs, configuration and exit code are all retained, its name is still taken, and you can inspect it, copy files out of it, or start it again. A removed container is gone entirely and its writable layer's disk is reclaimed. That is why `docker ps -a` on a long-lived host often lists hundreds of exited containers quietly consuming space.
- How does `docker restart` differ from removing a container and running a new one from the same image?`docker restart` stops and starts the *same* container object — same ID, same name, same configuration and, importantly, the same writable layer, so files written during the previous run are still present. Running a fresh container from the image gives a brand-new writable layer, so anything written outside a volume during the old run is gone.
saying these in an interview costs you the question
- Treating exited as meaning the container no longer exists or consumes disk
- Thinking `dead` just means "stopped" or "crashed"
- Believing paused containers have been signalled or given a chance to shut down
- Saying `docker restart` creates a new container from the image
- Claiming `docker ps` shows all containers by default (it only shows running ones)