Container Lifecycle — Every State a Container Can Be In
What Is the Container Lifecycle in Simple Terms?
Every Docker container exists in exactly one state at any moment. Those states have names, and specific commands move a container from one state to another. Understanding this lifecycle is what lets you know the difference between a container that stopped because it finished its work (exit code 0) versus one that crashed (exit code 1) versus one that was killed (exit code 137).
Bash
docker create | v+------------------------------------------+| CREATED || Container created but process not started|| docker ps -a shows it, docker ps does not|+------------------------------------------+ | docker start | v+------------------------------------------+| RUNNING || Container process is executing || docker ps shows it |+------------------------------------------+ | | | docker pause docker stop docker kill | (SIGTERM) (SIGKILL) v | |+----------+ v v| PAUSED | +------------------+ || Process | | STOPPED (EXITED) |<-+| frozen | | Process finished || SIGSTOP | | docker ps -a shows|+----------+ +------------------+ docker unpause | | docker start v | docker rm RUNNING RUNNING | v DELETEDAll Five States Explained
Bash
# CREATED — exists but not starteddocker create --name my-nginx nginxdocker ps # not shown (not running)docker ps -a # shown with status Created # RUNNING — process is executingdocker start my-nginxdocker ps # shown with status Up # PAUSED — process is frozen (SIGSTOP)docker pause my-nginxdocker ps # shown with status Up (Paused)# Process is suspended — not using CPU# Memory is preserved — instant resume # STOPPED (EXITED) — process has endeddocker unpause my-nginx # resume from pauseddocker stop my-nginx # send SIGTERMdocker ps # not showndocker ps -a # shown with status Exited (0) # DELETED — container no longer existsdocker rm my-nginxdocker ps -a # gone completelyExit Codes — Why a Container Stopped
Bash
# See exit code of a stopped containerdocker ps -a --format 'table {{.Names}}\t{{.Status}}'# NAMES STATUS# api Exited (0) 2 minutes ago <- clean exit# worker Exited (1) 5 minutes ago <- application error# processor Exited (137) 1 minute ago <- OOMKilled or docker kill # Decode exit codes:# 0 = clean exit (batch job finished, intentional stop)# 1 = generic application error# 126 = cannot execute (permission denied)# 127 = command not found# 137 = SIGKILL (OOMKilled or docker kill)# 143 = SIGTERM (docker stop or graceful shutdown) # Check OOMKilled specificallydocker inspect api --format '{{.State.OOMKilled}}'# true -> exceeded memory limit# false -> some other causeRestart Policies and Lifecycle
Bash
# Restart policies affect what happens after STOPPED state: # no (default) — stays stoppeddocker run --restart=no nginx# Crashes -> stays in EXITED state # on-failure — restart only on error exit codedocker run --restart=on-failure:5 payment-api# Exits with code 0 -> stays EXITED# Exits with code 1 -> restarts (up to 5 times) # always — always restartdocker run --restart=always nginx# Any exit -> restart (including clean exit)# Survives daemon restart (starts on boot) # unless-stopped — restart unless manually stoppeddocker run --restart=unless-stopped trading-engine# docker stop -> stays stopped (respects manual stop)# Crash -> restarts# Daemon restart -> restarts (starts on boot)Complete Lifecycle Commands
Bash
# Full lifecycle from creation to deletiondocker create --name api nginx # CREATEDdocker start api # RUNNINGdocker pause api # PAUSEDdocker unpause api # RUNNINGdocker stop api # STOPPEDdocker start api # RUNNING againdocker kill api # STOPPED (SIGKILL)docker rm api # DELETED # Shortcut: run = create + startdocker run -d --name api nginx # RUNNING directly # Shortcut: rm -f = kill + rmdocker rm -f api # DELETED directlyPLACEMENT PRO TIP**Tip:** Use `docker events` to watch container lifecycle events in real time. It shows every state transition with a timestamp — useful for understanding why a container keeps restarting or when exactly it crashed.
REMEMBER THIS**Remember:** `docker stop` sends SIGTERM and waits 10 seconds for a clean exit before sending SIGKILL. `docker kill` sends SIGKILL immediately. Applications that handle SIGTERM (flush buffers, close connections, finish in-flight requests) need `docker stop` — not `docker kill` — to shut down cleanly.