skip to content

What does the `docker pause` command actually do to a container, how is it implemented in the Linux kernel, and how is it different from stopping the container?

level: middleimportance: should knowfreq 30%

answer

  1. freezer cgroup: freezer.state=FROZEN (v1) / cgroup.freeze=1 (v2)
  2. No signal sent — app never knows
  3. Memory kept, RAM not freed
  4. Clock keeps running: peers time out, health checks fail
  5. exec into a paused container hangs

basics

~20 s

docker pause freezes every process in the container using the kernel's freezer cgroup — no signal is sent, memory stays resident, nothing is scheduled. docker unpause resumes exactly where it left off. Stopping instead signals the process to terminate and frees its memory.

solid answer

~50 s

`docker pause` suspends all processes in a container by writing to the **freezer cgroup** — `freezer.state = FROZEN` under cgroup v1, or `cgroup.freeze = 1` under cgroup v2. The kernel stops scheduling those tasks. Critically, **no signal is delivered**: the application gets no notification, cannot run cleanup, and cannot refuse. `docker unpause` thaws them and execution continues from the exact instruction. Stopping is completely different: `docker stop` sends SIGTERM (then SIGKILL after the grace period), the process terminates, and its memory is released. The container ends up in `exited` with an exit code. What pausing preserves: memory, open file descriptors, and TCP sockets — which is also the catch. Wall-clock time keeps moving while the container is frozen, so peers time out, health checks fail, keepalives lapse and TLS or session state can expire. Pause is useful for short operations — quiescing a filesystem for a snapshot, freeing CPU contention momentarily, debugging a race — not as a way to "park" a service.

code

bash · 4 lines
bash
docker pause db
docker ps --filter name=db --format '{{.Names}} {{.Status}}'
docker inspect -f '{{.State.Status}} {{.State.Paused}}' db
docker unpause db

go deeper

for a junior

Know that pause freezes the processes without terminating them and that unpause resumes them exactly where they were, unlike stop.

for a middle

Name the freezer cgroup mechanism and the v1/v2 knobs, and explain that memory is retained and no signal is sent.

for a senior

Reason about the consequences — timeouts, keepalives, failing health checks, exec hanging — and pick pause only for short, bounded operations like snapshot quiescing.

for a principal

Position pause as a low-level primitive for snapshot/debug workflows, not a capacity-management tool; scaling to zero and stopping are the correct answers for reclaiming resources.

## The mechanism Every Docker container's processes live in a cgroup hierarchy. One of those controllers is the **freezer**, whose entire job is to atomically suspend and resume a group of tasks. - **cgroup v1**: the daemon writes `FROZEN` to `freezer.state` in the container's freezer cgroup; `THAWED` resumes. - **cgroup v2**: it writes `1` to `cgroup.freeze`; `0` resumes. The kernel moves every task in the group into an uninterruptible frozen state and stops scheduling them. This is atomic with respect to the group — you never get half a container frozen — and it is transparent: the processes have no way to observe, delay, or decline it. `docker unpause` writes the opposite value and the tasks resume at the exact instruction they were stopped on. This is the same mechanism the kernel uses for system suspend and for checkpoint/restore tooling, which is why it also underpins container snapshotting workflows. ## What pause is not Pause is **not** a signal. SIGSTOP is the signal-based cousin, but Docker deliberately uses the freezer cgroup instead: SIGSTOP can be raced by the process, applies per-process rather than atomically to a group, and can be seen by a parent through wait status. The freezer avoids all of that. Pause is **not** a lifecycle event the application participates in. Compare with `docker stop`, which sends SIGTERM and gives the app a documented window to drain connections, flush buffers and exit. A paused application knows nothing, does nothing, and cannot prepare. ## What is preserved, and what that costs you On pause, the container keeps: - its resident memory (the RAM is **not** freed — a paused container still counts against host memory), - open file descriptors and mmaps, - established TCP connections (the sockets stay open in the kernel; only the userspace processes are frozen), - its network namespace, IP, and published port bindings. But the world does not pause with it. Wall-clock time advances, so: - peers waiting on a response hit their timeouts and give up, - TCP keepalives and application heartbeats lapse; clustered systems may evict the node, - kernel socket receive buffers fill and the peer's window closes, eventually stalling or resetting the connection, - Docker health checks cannot execute (they run inside the frozen container), so the container is marked unhealthy, - leases, session tokens and TLS session tickets can expire. So pause is safe for **seconds**, dangerous for minutes. A frozen database or a frozen cluster member is a partition from everyone else's point of view. ## Legitimate uses 1. **Quiescing for a consistent snapshot** — freeze the processes so nothing writes while you snapshot a filesystem or volume, then unpause. 2. **Debugging a race or a heisenbug** — stop the world mid-flight and inspect state from the host (`/proc/<pid>` of the container process, mounted filesystem, etc.) without letting execution continue. 3. **Momentary CPU relief** — free up contention for a short burst of higher-priority work on the same host, without losing the container's warm state. 4. **Checkpoint/restore workflows** built on the same freezer primitive. What it is not good for: "parking" an idle service to save resources. Memory is not freed, connections rot, and health monitoring fails. Stopping the container is the honest way to release resources; scaling to zero is the orchestrator-level answer. ## Observing it `docker ps` shows `Up 5 minutes (Paused)`. `docker inspect -f '{{.State.Status}} {{.State.Paused}}'` returns `paused true`. On the host, the container's processes appear in state `D` and consume no CPU while `docker stats` shows the memory still charged to the container. One practical hazard: `docker exec` into a paused container will hang, because the new process is created in a frozen cgroup and immediately freezes too. Unpause first. Similarly, `docker stop` on a paused container has to unpause it to deliver signals, so if you need it gone, `docker unpause` then `docker stop`, or `docker kill`/`docker rm -f`.

  • Does pausing a container free the memory it was using?
    No. The freezer cgroup only stops the tasks from being scheduled; their address spaces remain resident and still count against the container's memory limit and the host's RAM. If your goal is to reclaim memory you must stop the container, which terminates the processes and releases their memory.
  • Why does Docker use the freezer cgroup rather than sending SIGSTOP to the container's processes?
    The freezer suspends the entire cgroup atomically, so you never catch the container half-frozen, and the processes cannot observe, race, or interfere with it. SIGSTOP is per-process, can be raced by a process that is forking, and is visible to a parent through wait status. The freezer is also the same primitive used for system suspend and checkpoint/restore.
  • What happens if you run `docker exec` against a paused container?
    It hangs. The new process is created inside the container's frozen cgroup and is immediately frozen along with everything else, so it never produces output. You have to `docker unpause` first. For the same reason health checks, which execute inside the container, cannot run while it is paused.

Pause is hitting pause on a film: every frame is preserved exactly. But the audience's watches keep ticking, so if you leave it paused too long everyone has walked out.

saying these in an interview costs you the question

  • Believing pause frees the container's memory or reclaims resources
  • Thinking pause sends SIGSTOP or any signal the application can handle
  • Assuming the application gets a chance to save state before being paused
  • Treating pause as a safe way to park a service for a long period
  • Expecting `docker exec` or health checks to work on a paused container

context