Docker Resource Limits¶
Monitor Container Resource Usage¶
docker stats streams real-time CPU, memory, network I/O, and block I/O metrics for running containers.
By default, Docker containers have no resource limits. If you do not specify any constraints, a single container can consume 100% of the host machine's CPU and Memory. This is extremely dangerous—if a single container experiences a memory leak or a massive traffic spike, it can completely crash the underlying host server, taking down all other containers with it!
graph TD
HOST["🖥️ Host Resources"]
HOST-->CPU["⚡ CPU
--cpus=0.5
(50% of 1 core)"]
HOST-->MEM["🪣 Memory
--memory=256m
(hard cap)"]
HOST-->PID["📊 PIDs
--pids-limit=100
(fork bomb protection)"]
CPU-->CNT["📦 Container
(resource-constrained)"]
MEM-->CNT
PID-->CNT
style HOST fill:#f3f4f6,stroke:#9ca3af,stroke-width:2px,color:#1f2937
style CPU fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a
style MEM fill:#ffedd5,stroke:#f59e0b,stroke-width:2px,color:#78350f
style PID fill:#cffafe,stroke:#06b6d4,stroke-width:2px,color:#164e63
style CNT fill:#dcfce7,stroke:#22c55e,stroke-width:2px,color:#14532d
Start a container that consumes some CPU.
docker run -d --name loadtest alpine:3.22 sh -c "while true; do :; done"
c1d2e3f4g5h6i7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4a5b6c7d8e9f0g1h2
Run docker stats --no-stream loadtest to take a single snapshot of its resource usage. Notice under the CPU % column that this single container is consuming an enormous amount of CPU (often pinning a whole core) because there are no limits in place!
docker stats --no-stream loadtest
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c1d2e3f4g5h6 loadtest 100.00% 1.141MiB / 7.765GiB 0.01% 1.03kB / 0B 0B / 0B 1
Run docker stop loadtest && docker rm loadtest to clean up.
docker stop loadtest && docker rm loadtest
loadtest
loadtest
Set a CPU Limit¶
The --cpus flag limits the number of CPU cores a container may use. A value of 0.25 means the container can consume at most 25% of one CPU core.
Run a container with a CPU limit and a heavy load loop.
docker run -d \
--name cpulimited \
--cpus=0.25 \
alpine sh -c "while true; do :; done"
b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2g3
Now, check its CPU usage by running docker stats --no-stream cpulimited.
docker stats --no-stream cpulimited
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
b2c3d4e5f6g7 cpulimited 25.02% 1.23MiB / 7.765GiB 0.02% 906B / 0B 0B / 0B 1
Unlike Task 1 (where the CPU spiked out of control), you will see the CPU % is now firmly locked at exactly 25.00%!
Why doesn't it crash? When a container hits a memory limit, the Linux kernel has no choice but to kill it because there is physically no more RAM to allocate. But when a container hits a CPU limit, the kernel simply throttles it using the Completely Fair Scheduler (CFS). The container doesn't crash; it just runs slower, receiving exactly the CPU quota it was assigned!
Set a Memory Limit¶
The --memory flag caps the maximum RAM a container can use. If the container exceeds this limit, the Linux kernel OOM (Out Of Memory) killer forcefully terminates it.
Run a container with a 64MB memory limit.
docker run -d --name memlimited --memory=64m nginx:alpine
f1e2d3c4b5a6z7y8x9w0v1u2t3s4r5q6p7o8n9m0l1k2j3i4h5g6f7e8d9c0b1a2
Verify the limit is applied. Note: 67108864 bytes = 64MB.
docker inspect memlimited --format '{{.HostConfig.Memory}}'
67108864
Let's prove the OOM killer works! Run a new 10MB limited container that intentionally consumes memory in an infinite loop:
docker run -d \
--name oom_test \
--memory=10m \
alpine sh -c "x=a; while true; do x=\$x\$x; done"
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
Wait a few seconds, then run docker ps -a and look at the STATUS column for your container. You will see it has unexpectedly stopped (e.g., Exited (137)).
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 alpine "sh -c 'x=a; while t…" 5 seconds ago Exited (137) 3 seconds ago oom_test
f1e2d3c4b5a6 nginx:alpine "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp memlimited
b2c3d4e5f6g7 alpine "sh -c 'while true; …" 5 minutes ago Up 5 minutes cpulimited
But why did it exit? Let's dig deeper. Inspect the container's state and look closely at the JSON output for the "OOMKilled" field. It will be set to true!
docker inspect oom_test --format '{{json .State}}' | jq
{
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": true,
"Dead": false,
"Pid": 0,
"ExitCode": 137,
"Error": "",
"StartedAt": "2023-11-01T12:30:01.000000000Z",
"FinishedAt": "2023-11-01T12:30:03.000000000Z"
}
Inspect Process List¶
docker top displays the running processes inside a container, similar to the Unix top command but scoped to a single container.
Run docker top memlimited to list the Nginx processes inside the memory-limited container.
docker top memlimited
UID PID PPID C STIME TTY TIME CMD
root 1234 1211 0 12:28 ? 00:00:00 nginx: master process nginx -g daemon off;
101 1277 1234 0 12:28 ? 00:00:00 nginx: worker process
101 1278 1234 0 12:28 ? 00:00:00 nginx: worker process
View System-Wide Resource Usage¶
docker system df shows total disk usage broken down by images, containers, and volumes. Running containers with resource limits helps prevent a single container from impacting the entire host.
Run docker system df to see overall disk utilisation.
docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 1 120MB 40MB (33%)
Containers 3 2 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0B
Run docker stats --no-stream to see all running containers and their current resource consumption.
docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
f1e2d3c4b5a6 memlimited 0.00% 2.34MiB / 64MiB 3.66% 1.2kB / 0B 0B / 0B 3
b2c3d4e5f6g7 cpulimited 25.04% 1.23MiB / 7.765GiB 0.02% 1.5kB / 0B 0B / 0B 1
🧠 Quick Quiz¶
What happens if a container exceeds its hard memory limit (--memory)?
What happens if a container hits its CPU limit (--cpus)?
Which command provides a real-time, top-like view of resource usage for all running containers?
Practice Live in Your Browser
Don't just read about Docker commands—execute them in real time! Launch a fully-configured, secure Docker sandbox directly in your browser with automated task validation ready for you.
📬 DevopsPilot Weekly — Learn DevOps, Cloud & Gen AI the simple way.
👉 Subscribe here