Read Live Container CPU and Memory with docker stats

Something on the host is chewing CPU or memory, and docker container stats (also docker stats) tells you which container it is. You will read live CPU, memory, network, block I/O and process counts, then take a single sample and print a compact table for one named container. Allow about ten minutes.

If your Docker setup restricts access to the daemon socket, fix that access according to your host policy. Do not bolt elevated privileges onto every monitoring command.

1. Check the command and the daemon

Confirm which executable you will run, then list the containers that the current Docker context can see:

$ docker version --format '{{.Client.Version}}'
29.8.1
$ docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}'
CONTAINER ID   NAMES          STATUS
abc123def456   example-web    Up 12 minutes

The container ID and name in your output will differ. Keep one of them for the next step.

Tip: if the command says it cannot connect to the daemon, check docker context show and the daemon service before troubleshooting statistics. Do not start or restart a service just because the output is empty: first establish whether you are using the intended context.

Checkpoint: you have a running container name or ID, and docker ps completed successfully.

2. Watch all running containers

Run the command with no container arguments:

$ docker container stats
CONTAINER ID   NAME          CPU %   MEM USAGE / LIMIT   MEM %   NET I/O        BLOCK I/O     PIDS
abc123def456   example-web   0.02%   18.4MiB / 2GiB      0.90%   12.1kB / 0B    0B / 0B       6

The display refreshes as a live stream until you press Ctrl-C. Read the columns like this:

For one stable sample, interrupt the stream and use --no-stream:

$ docker container stats --no-stream example-web
CONTAINER ID   NAME          CPU %   MEM USAGE / LIMIT   MEM %   NET I/O        BLOCK I/O     PIDS
abc123def456   example-web   0.02%   18.4MiB / 2GiB      0.90%   12.1kB / 0B    0B / 0B       6

The exact values change between runs. Verify the command returned normally with printf '%s\n' "$?" immediately afterwards.

Tip: a successful sample is evidence about that instant, not a diagnosis of a long-running workload.

3. Narrow the view to named containers

Pass one or more names or IDs separated by spaces. This helps when a busy host makes the all-container view hard to scan:

$ docker container stats --no-stream example-web example-worker
CONTAINER ID   NAME             CPU %   MEM USAGE / LIMIT   MEM %   NET I/O       BLOCK I/O   PIDS
abc123def456   example-web      0.02%   18.4MiB / 2GiB      0.90%   12.1kB / 0B   0B / 0B     6
def456abc123   example-worker   0.01%   22.7MiB / 2GiB      1.11%   8.2kB / 0B    0B / 0B     8

A stopped container can be named, but it does not return live statistics. If a name is misspelled, Docker reports that it cannot find the container. Use docker ps -a --format '{{.ID}} {{.Names}} {{.Status}}' to check both running and stopped names without changing state.

4. Include stopped containers when needed

Add --all when the inventory must include stopped containers:

$ docker container stats --all --no-stream
CONTAINER ID   NAME           CPU %   MEM USAGE / LIMIT   MEM %   NET I/O       BLOCK I/O   PIDS
abc123def456   example-web    0.02%   18.4MiB / 2GiB      0.90%   12.1kB / 0B   0B / 0B     6
fedcba654321   old-worker     0.00%   0B / 0B             0.00%   0B / 0B       0B / 0B     0

This option changes the set of containers considered. It does not start the stopped ones. Stopped rows normally contain no live workload, so use them for inventory, not as recent performance measurements.

5. Choose a small, scriptable format

The default table suits people. A narrow template is easier to read in a terminal or log. Use the documented placeholders and quote the template so the shell does not interpret its braces:

$ docker container stats --no-stream \
    --format 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.PIDs}}' \
    example-web
NAME          CPU %   MEM USAGE / LIMIT   PIDS
example-web   0.02%   18.4MiB / 2GiB      6

Without the table prefix, Docker emits only the fields requested and no header:

$ docker container stats --no-stream --format '{{.Name}} {{.CPUPerc}} {{.MemPerc}}' example-web
example-web 0.02% 0.90%

For one JSON object per container, use the special json format:

$ docker container stats --no-stream --format json example-web
{"BlockIO":"0B / 0B","CPUPerc":"0.02%","Container":"abc123def456","ID":"abc123def456","MemPerc":"0.90%","MemUsage":"18.4MiB / 2GiB","Name":"example-web","NetIO":"12.1kB / 0B","PIDs":"6"}

Warning: the values are formatted strings, not numeric JSON fields. A script that needs arithmetic should parse them deliberately and account for units and the trailing percent sign. For machine integrations that need raw counters or a different sampling model, use the Docker API rather than assuming the display strings are a stable schema.

6. Avoid the common traps

Done means