Running Containers
Measured on Docker Desktop 4.81.0 / Engine 29.6.1 (macOS, linux/arm64), 2026-09-30.
What is a container?
Section titled “What is a container?”An image is a blueprint. A container is a live, running instance of that blueprint — an isolated process with its own filesystem view, network, and process space, all sharing the host kernel.
You can run many containers from the same image, stop and restart them, inspect their logs, and remove them when you are done. Understanding this lifecycle is the foundation of working with Docker day to day.
The container lifecycle
Section titled “The container lifecycle”The engine reports one of seven states in docker inspect --format '{{.State.Status}}' (the older four-state summary of “created, running, stopped, removed” leaves out the ones you will meet while debugging):
| State | What it means | How you get there (proven) |
|---|---|---|
| created | The container exists but its process has never been started. | docker create, Status=created |
| running | The main process is executing. | docker start / docker run |
| paused | Processes are frozen with the cgroup freezer; memory stays allocated. | docker pause → Status=paused Running=true Paused=true, ps shows Up … (Paused) |
| restarting | A restart policy is between attempts after an exit. | --restart always on a command that exits 1 → Status=restarting ExitCode=1, ps shows Restarting (1) |
| exited | The main process ended (or docker stop). The container, its writable layer, logs and exit code still exist on disk. | docker stop → Status=exited ExitCode=137 for a sleep that ignored SIGTERM |
| removing | docker rm is in progress. Very short-lived. | Listed by the docker container ls status filter |
| dead | A “defunct” container: removal only partly succeeded because something kept a resource busy. It cannot be restarted, only removed (per the docs). Rare — we could not produce one on demand. | Same docs table |
After docker rm completes there is no state at all: it deletes the container and its writable layer, and the container stops appearing anywhere.
flowchart LR created["created"] -->|docker start| running["running"] running -->|docker pause| paused["paused"] paused -->|docker unpause| running running -->|process exits or docker stop| exited["exited"] exited -->|docker start| running running -->|crash with a restart policy| restarting["restarting"] restarting --> running exited -->|docker rm| removed["gone (removed)"] created -->|docker rm| removed
The real docker inspect lines for the first four:
created Status=created Running=false Paused=false Restarting=false ExitCode=0running Status=running Running=true Paused=false Restarting=false ExitCode=0paused Status=paused Running=true Paused=true Restarting=false ExitCode=0exited Status=exited Running=false Paused=false Restarting=false ExitCode=137restarting Status=restarting Running=true Paused=false Restarting=true ExitCode=1Note Running=true while paused or restarting: filter on .State.Status, not .State.Running, when you need the exact state.
docker run → created + runningdocker stop → exiteddocker start → running again (same container, same writable layer)docker rm → removed (gone)What this module covers
Section titled “What this module covers”| Lesson | Topic |
|---|---|
| Lifecycle | docker run, docker ps, docker stop/start/restart, docker rm, --rm, exit codes |
| Exec & Logs | docker exec -it, docker logs, docker top, attaching, log rotation |
| Ports & Env | Publishing ports -p, environment variables -e / --env-file, naming --name |
| Restart & Inspect | Restart policies, docker inspect, docker stats, resource limits |
Quick demo — run, list, and stop
Section titled “Quick demo — run, list, and stop”The commands you will use most in this module:
#!/bin/sh# Pull and run nginx in the backgrounddocker run -d --name demo nginx:1.31-alpine# List running containersdocker ps# Stop itdocker stop demo# Remove itdocker rm demoCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESc0d6336221c2 nginx:1.31-alpine "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 80/tcp demo80/tcp with no arrow means the image declares port 80 (EXPOSE) but nothing is published to the host.
# Pull and run nginx detached
docker run -d --name demo nginx:1.31-alpine
# Confirm it is running
docker ps
# Stop the container
docker stop demo
# Remove it
docker rm demo
# Confirm it is gone
docker ps -aReading AI-generated code
Section titled “Reading AI-generated code”An AI-written health probe for a deploy script:
🐛 Spot the bug
#!/bin/sh# AI: "fail the deploy if the web container is not running"if [ -z "$(docker ps -q --filter name=web)" ]; thenecho "web is down" >&2exit 1fiecho "web is up"Show the answer
--filter name= is a substring/regex match on the container name, not an equality test. If the real web container is gone but a container named webhook (or web-old) is running, the probe passes. Reproduced with names shortened from docker-b1-web / docker-b1-webhook (only the second container existed):
$ docker ps -q --filter name=web | wc -l1$ docker ps --filter name=web --format '{{.Names}}'webhook$ docker ps -q --filter 'name=^web$' | wc -l0$ docker inspect -f '{{.State.Running}}' weberror: no such object: webAnchor the pattern, or better, ask about the exact container and its state:
#!/bin/shset -eustate=$(docker inspect -f '{{.State.Status}}' web 2>/dev/null || echo missing)if [ "$state" != "running" ]; then echo "web is $state" >&2 exit 1fiecho "web is up"docker inspect on a missing container exits non-zero with no such object, which the || echo missing turns into a state instead of an accidental pass.
Mental Model
Section titled “Mental Model”A container is a row in the engine’s database plus a process (when running) plus a writable layer on disk. docker stop only ends the process; the row and the layer stay until docker rm. Most confusion in this module — “where did my container go?”, “why is the disk full?”, “why does my name conflict?” — is forgetting that the row outlives the process.
Trade-offs
Section titled “Trade-offs”| Choice | Benefit | Cost |
|---|---|---|
| Keep exited containers | Exit code, logs and writable layer stay inspectable | They accumulate disk and hold their names |
--rm | Self-cleaning one-shot containers | Nothing left to inspect after a crash |
docker pause | Freeze without losing memory state or PID | Memory stays allocated; network peers see a stalled service |
Common Misconceptions
Section titled “Common Misconceptions”- “A stopped container is deleted.” It is
exitedand still listed bydocker ps -a, with its writable layer. - “Running=true means the process is doing work.” A paused container also reports
Running=true; check.State.Status. - “
docker psshows every container.” Only running ones (and paused/restarting). Add-afor the rest. - “
docker ps --filter name=xfinds containerx.” It finds every container whose name contains or matchesx.