The problem: one container can affect an entire server
Docker makes it easy to run multiple applications — or multiple instances of the same application — on a single physical server. A typical production server might host four containers on four CPU cores, each using a modest, predictable slice of CPU.
But what happens when one container suddenly needs much more CPU? A traffic spike, a large batch job, a background task processing unexpected data, or a bug causing a process to spin — any of these can turn a well-behaved container into a resource hog.
Four containers run on top of four shared cores. How much of each core a container can use depends on its CPU configuration.
Without any CPU management, Docker does not automatically prevent one container from using most of the server's CPU:
On a four-core server, 390% CPU means one container is consuming almost all available CPU. The others are still running, but they slow down as they compete for what's left — leading to slow response times, increased latency, failed health checks, unstable services, and difficulty even accessing the server.
Docker provides two main mechanisms, and they solve different problems: --cpus (CPU limits) and --cpu-shares (CPU shares).
CPU limits: setting a maximum CPU amount
A CPU limit defines the maximum CPU a container is allowed to consume. For example, docker run --cpus=1 means the container can use at most one CPU core — even if the other three cores on the server are completely unused.
Think of CPU limits like a speed limit on a highway. If the limit is 60 mph, you can't drive faster even if the highway is empty.
Why CPU limits are useful
CPU limits are mainly used for protection. If a bug causes one container to enter a CPU-intensive loop, an unlimited container would spike to 390% and starve everything else. With --cpus=2 set on that container, it's capped at roughly two cores — the problem stays isolated, and the remaining capacity is available for other containers, the OS, monitoring tools, and administrative access.
The limitation of CPU limits
CPU limits provide protection, but they can also waste performance. If every container on a 4-core server is capped at --cpus=1, and only one of them is busy while the other three sit idle, the busy container still can't exceed its 1-core cap — even though three full cores are going unused. For bursty workloads, that's not ideal. This is where CPU shares come in.
CPU shares: sharing CPU fairly
CPU shares work differently. Instead of defining a maximum amount of CPU, shares define how CPU should be divided when multiple containers need it at the same time.
A common misconception: setting --cpu-shares=1024 does not mean a container is capped at some percentage of CPU. CPU shares are not a limit. They don't reserve CPU, and they don't prevent a container from using all available CPU — they only influence distribution during contention.
- Hard maximum — a container can never cross it
- Protects the host against runaway CPU usage
- May leave idle CPU capacity unused
- Relative priority, not a hard cap
- Better overall resource utilization
- Only matters once containers compete for CPU
Scenario walkthrough: four instances, equal shares
Imagine two servers with four CPU cores each, running eight instances total, every one configured with --cpu-shares=1024. Because every instance has the same share value, Docker treats them equally — but the outcome still depends entirely on who else is competing.
A container with CPU shares can still consume the entire server when nothing else is competing — shares only kick in once there's contention.
Increasing priority with CPU shares
Shares can also express relative priority. If Instance 1 is set to cpu-shares=2048 while Instances 2–4 stay at 1024, Instance 1 has twice the share value. When all four compete, Instance 1 receives roughly twice the CPU of each of the others — but if the others are idle, Instance 1 can still use whatever's available. Shares influence fairness, not maximum usage.
How Docker CPU shares work internally
Docker relies on the Linux CPU scheduler, which continuously checks which containers need CPU, how much CPU time each has already received, and what their configured weights are. It then distributes CPU time in very small intervals. Over time, usage follows the configured share ratios — but it's not a fixed allocation; it adapts dynamically to the actual workload.
CPU shares vs. CPU limits
The easiest way to remember the difference is by the question each one answers:
At a glance
Can we use both together?
Yes — many production systems do. A common pattern combines CPU shares of 1024 across all instances for fair sharing during normal operation, with a CPU limit of 2 cores per instance as a ceiling. That gives fair CPU sharing day-to-day, and protection against any single container going rogue.
Final takeaways
--cpus) create a hard ceiling.--cpu-shares) control fairness, not a maximum.Have a similar infrastructure or resource-management problem you're working through?
Get in touch