DEV Community

Srinivasaraju Tangella
Srinivasaraju Tangella

Posted on

The Complete Docker Container Lifecycle: States, Namespaces, and Internal Workings

DOCKER CONTAINER LIFECYCLE — FROM ZERO TO ADVANCED LEVEL

A Docker container goes through a full lifecycle just like a Linux process, but with additional layers:

Image pulling

Filesystem creation (UnionFS)

Namespace + cgroup setup

Network setup

Entry process execution

Stop / restart / remove

Cleanup (volumes/networks)

Let’s start from the absolute beginning.


1️⃣ PRE-STAGE: Image Preparation

Before a container exists, Docker must prepare the image:

Steps

1.docker pull ubuntu

2.Docker stores image layers under /var/lib/docker//

3.A parent filesystem is prepared using UnionFS (overlay2).

No namespaces yet.

Only when we create or run the container, Docker sets namespaces.


2️⃣ CREATION STAGE: docker create

docker create prepares the container without starting the process.

docker create --name myc ubuntu sleep 100

What happens internally

1.Docker allocates a Container ID

2.Prepares the read-write layer over the image’s read-only layers

3.Creates a container metadata JSON in:

/var/lib/docker/containers//config.v2.json

Namespace creation happens here (critical)

Docker sets up namespaces but does not attach the process yet.

Namespaces created:

Namespace purpose:

mnt: Container filesystem mount points
pid: Separate process tree
uts: Hostname/domainname inside container
ipc: Shared memory, semaphores
net: Virtual Ethernet (veth) + network stack
user :(optional) UID/GID mapping

Namespaces are pre-configured, but NO process is running yet inside them.

Container State after docker create

State: created

You can check:

docker ps -a


3️⃣ START STAGE: docker start

docker start myc

This is when the real Linux process (container entrypoint) starts.

What happens internally

1.Docker forks a child process under container namespaces.

2.Applies cgroups:

CPU, Memory, PID limits

3.Sets rootfs using chroot + pivot_root

4.Executes entrypoint/CMD (like sleep 100).

Namespaces ACTIVE NOW

The process is running inside:

PID namespace (process 1 inside container)

Network namespace (separate network stack)

MNT namespace (isolated filesystem)

IPC namespace

UTS namespace

cgroups apply resource limits

Container State:

✔ running

Check via:

docker inspect -f '{{.State.Status}}' myc


4️⃣ RUNNING STATE — Active Execution

Container is now:

Running main PID

Attached to cgroups

Using its own namespaces

Maintaining logs

Connected to docker0 / bridge / custom network

When do we use this state?

✔ During application execution
✔ For monitoring logs
✔ For debugging using nsenter
✔ For updating filesystems, hot-changes, live testing

Entering namespaces of running container:

nsenter --target $(docker inspect -f '{{.State.Pid}}' myc) --pid --net --uts --ipc --mnt bash


5️⃣ PAUSED STATE (Advanced)

docker pause myc

Uses cgroups freezer subsystem.

Container process is frozen—not killed, not stopped.

When & where used? ✔ Debugging complex apps
✔ Troubleshooting race conditions
✔ Resource management

State: paused

Resume:

docker unpause myc


6️⃣ STOPPED STATE

Stopping a container:

docker stop myc

Internally:

1.Sends SIGTERM

2.Wait (default 10 sec)

3.If still alive → SIGKILL

Namespaces are destroyed only after process dies.

State: exited

Where used? ✔ Container upgrades
✔ Controlled shutdown
✔ Restart policies
✔ Debugging containers post-failure


7️⃣ RESTARTED STATE

If container has a restart policy:

docker run --restart=always ...

Docker will:

1.Stop existing process

2.Recreate minimal namespaces

3.Restart process

State temporarily = restarting


8️⃣ DEAD STATE

A rare state:

docker inspect

State: dead

Occurs when:

Docker daemon crashes during container operation

Filesystem or metadata corruption

Container kill failed

Used only for troubleshooting.


9️⃣ REMOVAL STAGE

docker rm myc

Internal actions:

1.Remove container metadata

2.Remove RW layer

3.Delete network namespace

4.Close logs

State: container no longer exists


🔟 POST-STAGE: Cleanups

Volume cleanup

docker volume rm

Network cleanup

docker network rm


🧠 DETAILED FINAL LIFECYCLE FLOW

IMAGE → create → (created)
→ start → (running)
→ pause/unpause (optional)
→ stop → (exited)
→ restart → (running)
→ kill → (exited)
→ rm → (removed)

Namespaces Involvement in Each Docker Container Lifecycle Stage:

When you run a container, namespaces do not suddenly appear at all stages. They participate differently depending on the container's state. Here is the correct and practical explanation in plain, continuous text:


1️⃣ docker create — Namespaces are prepared but not active

When you run docker create, Docker sets up the container’s configuration, root filesystem, and metadata.
At this stage, the namespaces are defined but no process has entered them yet.
There is no PID, no running task, so the namespaces exist only as a “plan”, not as an active isolation environment.


2️⃣ docker start — Process joins the namespaces

When you run docker start, Docker launches the container’s first process (PID 1).
This is the moment the process actually enters all namespaces: PID, NET, IPC, MOUNT, UTS, USER (if used).
So at this stage, the namespaces become active and isolate the process.

This is the real birth of the container.


3️⃣ Running state — Namespaces fully active

In the running state, the container is fully isolated using all its namespaces.
The process (PID 1) runs inside:

its own PID namespace,

its own network namespace,

its own mount namespace,

its own hostname/UTS namespace,

its own IPC namespace, etc.

This is the stage where namespaces are working at 100%.


4️⃣ Pause state — Namespaces unchanged

When you pause a container, Docker freezes the container’s processes using the cgroup freezer.
The processes stop executing instructions, but the namespaces remain exactly as they were.
Nothing changes in namespace setup.
Only process execution is temporarily stopped.

It’s like freezing a VM — all isolation stays intact.


5️⃣ Stop state — Namespaces removed once the process dies

When you stop a container, the main process receives SIGTERM → SIGKILL and exits.
As soon as the last process in the container dies, its namespaces are automatically destroyed because namespaces cannot exist without a process inside them.

Only container metadata remains; the isolation environment is gone.

DOCKER CONTAINER STATES — WHEN, WHY, AND REAL USAGE

Docker container states:

created → running → paused → exited → restarting → dead

Let’s explain each state:


1️⃣ CREATED STATE

➡ Happens when you run:

docker create ...

✔ When/Why You Use It

You use this state when:

1.You want to prepare a container but NOT run it yet

Example: Setting configuration or modifying filesystem before start.

docker create --name web nginx
docker cp custom.conf web:/etc/nginx/
docker start web

2.Pre-provisioning containers in CI/CD

Prepare them first → start later in batch.

3.Debugging container filesystem BEFORE RUN

Some engineers inspect root filesystem before app starts.

Reason this state exists:
It allows you to prepare everything about a container before running the main process, just like creating a VM but not powering it on.


2️⃣ RUNNING STATE

➡ Happens when the container’s main PID is active.

✔ When/Why You Use It

1.Application is actively running

Containers serve traffic or jobs.

2.Debug running services

You attach, exec, inspect logs:

docker exec -it cont bash
docker logs cont

3.Monitoring CPU, memory, IO

Using cgroups metrics.

4.Live troubleshooting

Check active network namespace, mounts, PIDs:

nsenter --target $(docker inspect -f '{{.State.Pid}}' cont) --net

Reason:
This is the actual “life” of the container — the application is fully executing.


3️⃣ PAUSED STATE

docker pause cont

Freezes the processes using cgroup freezer.

✔ When/Why You Use PAUSE

1.Debugging race conditions

Freeze container A, test container B for isolation.

2.Hot-maintenance of underlying host

Temporarily freeze containers without stopping them.

3.Resource protection

If container is consuming too much CPU, pause it without killing.

4.Live migration (rare)

Some orchestrators freeze containers before checkpoint/restore.

Reason:
Pause allows you to freeze running processes without killing them, useful for debugging, tuning, and resource control.


4️⃣ EXITED (STOPPED) STATE

docker stop cont
docker kill cont

✔ When/Why You Use EXITED

1.Stop app safely

docker stop gives graceful shutdown (SIGTERM → SIGKILL)

2.Keep logs and data for post-analysis

Stopped containers retain filesystem and logs.

3.Restart after configuration changes

Stop → modify → start again.

4.Investigate why app failed

Exit code:

docker inspect cont --format '{{.State.ExitCode}}'

5.CI pipelines

After job finishes, container moves to “exited”.

Reason:
Exited state keeps the container intact so DevOps can analyze, restart, debug, or fix problems without deleting it.


5️⃣ RESTARTING STATE

Happens when:

docker run --restart=always ...

✔ When/Why You Use RESTARTING

1.Autorecovery

If application crashes, Docker restarts it automatically.

2.Host reboot

All containers restart automatically (if policy is set).

3.Self-healing services

Basic container-level reliability even without Kubernetes.

Reason:
Makes container highly available even without orchestrators.


6️⃣ DEAD STATE

Rare state, appears only on issues.

✔ When/Why It Appears

1.Docker daemon crashed mid-operation

Container metadata becomes inconsistent.

2.Filesystem or cgroups failure

3.Force kill gone wrong

Docker couldn’t clean PID or release namespace.

Reason:
Dead state is for troubleshooting broken containers.
It indicates corruption or incomplete removal.


✔ When DevOps uses namespaces?

1.Network debugging

nsenter --net --target
ip a

2.Filesystem debugging

nsenter --mnt ...
mount

3.Security isolation testing

Check if apps see host processes:

nsenter --pid ...
ps -ef

4.IP/route issues

Debug inside container network namespace.

Top comments (0)