Memory Limits and Reservations
Memory Limits and Reservations
Setting Memory Limits
# Limit container to 512MB RAM
docker run -d --memory 512m myapp
# With swap (container can use 512MB + 256MB swap)
docker run -d --memory 512m --memory-swap 768m myapp
# No swap
docker run -d --memory 512m --memory-swap 512m myapp
# Memory reservation (soft limit)
docker run -d --memory 512m --memory-reservation 256m myapp
Memory Limits in docker-compose.yml
services:
api:
image: myapi
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
db:
image: postgres:16
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
Memory Flags Reference
| Flag | Description |
|---|---|
--memory / -m |
Hard memory limit |
--memory-reservation |
Soft memory limit |
--memory-swap |
Total memory (RAM + swap) |
--memory-swappiness |
Swap usage tendency (0-100) |
--kernel-memory |
Kernel memory limit |
--oom-kill-disable |
Disable OOM killer |
OOM Killer
When a container exceeds its memory limit, Linux kills it:
# Check if container was OOM-killed
docker inspect --format '{{.State.OOMKilled}}' web
# true
# Disable OOM killer (use with caution!)
docker run -d --memory 512m --oom-kill-disable myapp
# Set OOM score adjustment (-1000 to 1000)
docker run -d --oom-score-adj -500 myapp
Monitor Memory Usage
# Real-time memory stats
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
# Check specific container
docker inspect --format '{{.HostConfig.Memory}}' web
# 536870912 (512MB in bytes)
# Check cgroup memory limit
cat /sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes
Common Patterns
# Web server: 256MB-512MB
docker run -d --memory 512m nginx
# Node.js app: 512MB-1GB
docker run -d --memory 1g mynodeapp
# Java app: 70% of container memory for heap
docker run -d --memory 2g -e JAVA_OPTS="-Xmx1400m" myjavaapp
# Database: 4GB+
docker run -d --memory 4g postgres:16
CPU Limits and Shares
CPU Limits and Shares
CPU Limits
# Limit to 1.5 CPU cores
docker run -d --cpus 1.5 myapp
# Limit to 50% of one core
docker run -d --cpus 0.5 myapp
# CPU shares (relative weight, default 1024)
docker run -d --cpu-shares 512 myapp # Half the default
# Pin to specific CPUs
docker run -d --cpuset-cpus 0,1 myapp # Use CPU 0 and 1
# Combine limits
docker run -d --cpus 2 --cpuset-cpus 0,1 myapp
CPU in docker-compose.yml
services:
api:
image: myapi
deploy:
resources:
limits:
cpus: "2.0"
memory: 1G
reservations:
cpus: "0.5"
memory: 256M
worker:
image: myworker
deploy:
resources:
limits:
cpus: "1.0"
CPU Flags Reference
| Flag | Description |
|---|---|
--cpus |
Number of CPUs (decimal) |
--cpu-shares |
Relative weight (0-1048576) |
--cpuset-cpus |
Specific CPU cores |
--cpuset-mems |
Specific memory nodes |
I/O Limits
# Limit block I/O (bytes per second)
docker run -d --device-read-bps /dev/sda:10mb --device-write-bps /dev/sda:10mb myapp
# Limit I/O operations per second
docker run -d --device-read-iops /dev/sda:1000 --device-write-iops /dev/sda:1000 myapp
# Block I/O weight (10-1000, default 500)
docker run -d --blkio-weight 300 myapp
Network Bandwidth
Docker doesn't have built-in network bandwidth limiting. Use tc (traffic control) on the host:
# Limit container network to 10Mbit
tc qdisc add dev veth<container_id> root tbf rate 10mbit burst 32kbit latency 50ms
Resource Monitoring
# Real-time CPU and memory
docker stats --no-stream
# CPU usage over time
docker stats --format "{{.Name}} {{.CPUPerc}}" | while read line; do
echo "$(date +%H:%M:%S) $line"
sleep 1
done
# Find resource-hungry containers
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | sort -k2 -h -r