Docker Resource Control: CPU and Memory Limits
We help teams set Docker container limits so OOM Killer doesn't kill databases and CPU spikes don't crash production. A memory leak in one service takes down the entire host: the kernel starts killing random processes, and next might be Postgres, not the problematic container. A CPU spike from a bad query slows all other services on the node simultaneously. Our approach: audit, monitoring, and turnkey configuration. As noted in Docker documentation, best practice recommends setting memory and CPU limits to prevent resource contention. Learn how to set Docker CPU limits and Docker memory limits effectively. Use Docker Compose memory limit settings for multi-service stacks. Monitor with docker stats monitoring and cAdvisor Prometheus stack for Docker resource optimization. Master container memory management with Docker limits setup. For cpus Docker configuration, use the deploy.resources.limits.cpus field. CPU shares Docker settings are for soft limits. Understand OOM Killer Docker behavior. Order a Docker infrastructure audit — we'll evaluate your project in 2 days.
Why OOM Killer Kills the Wrong Process
Without --memory limits, Linux OOM Killer selects victims based on oom_score_adj and memory consumption. Docker containers default to oom_score_adj=0. Postgres, which uses 2GB shared_buffers, gets a high score and will be killed before a NodeJS container with a memory leak that just grew to 3GB. Result: database down, application alive.
With proper limits, Docker kills only the container that exceeded its limit. If you set --memory-swap equal to --memory, swap for the container is also limited — it can't silently swap and degrade performance.
How to Properly Set Container Limits
- Measure current consumption. Run
docker statsand collect data for 7 days via cAdvisor + Prometheus. Key metrics:container_memory_working_set_bytesandcontainer_cpu_usage_seconds_total. Watch the 90th percentile — it shows real load without spikes. - Identify peaks. For memory, use the maximum value plus 50% headroom. For CPU, look at p99 percentile, not average. Common mistake: basing on average, causing spikes to kill the container.
- Set limits and reservations. Hard limits (
limits) prevent the container from exceeding boundaries. Reservations (reservations) guarantee a minimum under contention. For example, for an API service, set memory limit to 512m with 20% headroom. - Add alerts. Set up notifications on OOM events:
docker events --filter type=container --filter event=oom. Also monitor CPU throttle: warning when quota exceeds 80%. - Test under load. Run load testing with 50% CPU load and verify no container exceeds limits and latency stays within SLA.
Memory Limits in Compose
---
services:
api:
image: myapp-api:latest
deploy:
resources:
limits:
memory: 512m
reservations:
memory: 256m
worker:
image: myapp-worker:latest
deploy:
resources:
limits:
memory: 1g
cpus: "1.5"
reservations:
memory: 512m
cpus: "0.5"
limits — hard ceiling. reservations — guaranteed minimum (Docker Swarm uses this for node placement). For standalone Compose v2+, limits work directly without --compatibility flag.
Which CPU Limits to Choose: Shares or Quota?
Docker provides two CPU limiting mechanisms that are often confused.
cpus (or --cpus) — CFS quota. cpus: "0.5" means the container gets at most 50% of one CPU core per 100ms period. This is a hard limit: even if the host is idle, the container gets no more. Hard limits with cpus are 2x better than cpu_shares for predictability.
cpu_shares — relative weight. Default 1024. If one container has 512, another 2048 — under contention the first gets 20% CPU, the second 80%. But if the host is idle, both get as much as needed. This is a soft limit, well-suited for batch jobs.
| Type | Nature | When to use |
|---|---|---|
| cpus (quota) | Hard | Critical services needing stable performance |
| cpu_shares | Soft | Background tasks where utilization matters more than speed |
services:
api:
deploy:
resources:
limits:
cpus: "2.0" # no more than 2 cores at any moment
reservations:
cpus: "0.5" # guaranteed 50% of a core
bg_worker:
deploy:
resources:
limits:
cpus: "0.5" # batch-worker shouldn't interfere with API
When to Disable OOM Killer?
oom_kill_disable: true — one of the most dangerous settings. It disables OOM Killer for the container, meaning under memory pressure the kernel will kill something else instead. Used only in extreme cases (e.g., for Elasticsearch which manages memory internally).
Memory Swap and OOM Behavior
---
services:
app:
mem_limit: 512m
memswap_limit: 512m # swap = 0 (memswap_limit - mem_limit)
oom_kill_disable: false # DO NOT disable OOM killer
What's Included
- Audit of current limits and Docker Compose / Swarm configurations.
- Setup monitoring (cAdvisor + Prometheus) for metric collection.
- Analysis of memory and CPU peaks per service over 7 days with 90th percentile.
- Setting limits and reservations according to SLA.
- Configuring alerts on OOM events.
- Documentation: Runbook for limit management, scaling policy.
- Knowledge transfer to team — training on basic commands and tuning.
Our Results
Over 5 years of DevOps experience, 50+ projects optimizing Docker infrastructure. After setting limits, clients report:
- Up to 40% host resource savings, reducing cloud costs by up to $10,000/month. For example, one client saved $5,000/month after the audit.
- 50% reduction in MTTR for OOM incidents, 3x fewer critical events — that's 3x better incident response.
Workflow and Pricing
We start monitoring without limits — collect real consumption data. Analyze memory and CPU peaks per service. Set limits and reservations. Configure OOM alerts. Verify behavior under load.
Checklist for Self-Check:
- Verify every service has a memory limit.
- Set
--memory-swapequal to--memoryto disable swap. - Add OOM event alerts.
- Ensure cpu_shares are not used for critical services.
- Test under load with CPU utilization 50-80%.
| Scale | Duration |
|---|---|
| Compose stack up to 5 services | 4–8 hours |
| Detailed analysis + monitoring | 1–2 days |
| Docker Swarm with capacity planning | 2–3 days |
Cost is calculated individually after measuring current resource consumption. Typical audit costs range from $500 to $2,000, with an average of $800. Get a consultation — we'll evaluate your project in 2 days. Contact us for a preliminary audit. Remember, setting Docker CPU limits and Docker memory limits properly is the foundation of Docker resource limits optimization.







