Without resource limits, a single misbehaving container can consume all available server resources, affecting every other container and service on the host. This guide covers configuring appropriate limits.
Why Resource Limits Matter
By default, Docker containers can use unlimited CPU and memory from the host — a runaway process (memory leak, infinite loop) in one container can starve every other container and the host system itself; limits contain the impact of any single container's misbehavior.
Setting Memory Limits
docker run -m 512m myapp
Limits the container to 512MB of memory — if it attempts to exceed this, the container's process is killed (OOM killed) rather than affecting the wider host.
Setting CPU Limits
docker run --cpus="1.5" myapp
Limits the container to 1.5 CPU cores worth of processing time — useful for preventing one container from monopolizing all available CPU.
Setting Limits in Docker Compose
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
limits sets the maximum; reservations sets a guaranteed minimum the container can rely on having available.
Determining Appropriate Limits
Monitor actual resource usage under normal and peak load (see Managing Docker Logs and general container monitoring) before setting limits — set limits with reasonable headroom above observed normal usage, not an arbitrary guess.
Monitoring Container Resource Usage
docker stats
Shows real-time CPU, memory, and I/O usage for all running containers — useful both for setting appropriate limits and for spotting a container approaching or hitting its configured limit.
What Happens When a Container Hits Its Memory Limit
The container's process is terminated by the OOM (Out of Memory) killer — configure appropriate restart policies (see Docker Restart Policies and Healthchecks Explained) so the container automatically restarts, though the underlying cause (why it needed more memory than allocated) should still be investigated.
Setting Swap Limits Alongside Memory
docker run -m 512m --memory-swap 1g myapp
--memory-swap sets the combined memory+swap limit — without this, a container might use swap unboundedly even with a memory limit set, since swap and memory limits are configured somewhat independently.
CPU Shares for Relative Priority (Alternative to Hard Limits)
docker run --cpu-shares=512 myapp
Rather than a hard cap, CPU shares set relative priority when the host is under CPU contention — a container with double the shares of another gets proportionally more CPU time when they're competing, but both can still use available CPU if there's no actual contention.
Applying Limits Across an Entire Compose Stack
Set appropriate limits for every service in a multi-container application, not just the ones that seem most resource-intensive — a supposedly lightweight service can still misbehave and consume unexpected resources without a configured limit.
Common Errors
Container repeatedly OOM-killed — either the limit is genuinely too low for the application's actual needs (increase it), or there's a real memory leak worth investigating (check application logs and behavior over time) rather than simply raising the limit indefinitely.
Continue Reading
- Docker Restart Policies and Healthchecks Explained
- How to Monitor Real-Time System Resources with htop and top
- How to Set Up Prometheus and Grafana for VPS Monitoring
Browse more articles in Docker & Containers.