4 KiB
| title | aliases | tags | sources | created | updated | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Docker Compose CPU Limits Break Per Environment |
|
|
|
2026-04-29 | 2026-04-30 |
Docker Compose CPU Limits Break Per Environment
Setting cpus: '4.0' in a prod docker-compose.yml and then running docker compose up on a server with only 2 CPUs causes a hard error. The fix is a per-environment compose override file that matches the target server's actual CPU count.
Key Points
- Error message:
"range of CPUs is from 0.01 to 2.00"— appears atdocker compose up, NOT atdocker compose build - The build succeeds silently; the failure only surfaces at container startup
- prod compose is the canonical config; environment-specific files override resource limits only
- Naming convention:
docker-compose.{env}.yml(e.g.docker-compose.optical-dev.yml)
Details
The error occurs because Docker enforces CPU limits against the host's actual CPU count at container start time, not at image build time. A prod file with cpus: '4.0' is valid on a 4-core prod server but fails immediately on a 2-core staging server.
Prod compose (canonical):
services:
ffmpeg-worker:
deploy:
resources:
limits:
cpus: '4.0' # valid on 4-core prod
memory: 8G
optical-dev override:
# docker-compose.optical-dev.yml
services:
ffmpeg-worker:
deploy:
replicas: 0 # also disable heavy workers on this env
resources:
limits:
cpus: '1.0' # optical-dev has 2 CPUs — keep 1 for other services
memory: 2G
Deploy command using override:
docker compose -f docker-compose.yml -f docker-compose.optical-dev.yml up -d
Pattern
| File | Role |
|---|---|
docker-compose.yml |
Canonical config — prod values, all services defined |
docker-compose.prod.yml |
Prod-specific overrides (rarely needed if base IS prod) |
docker-compose.optical-dev.yml |
optical-dev overrides — reduced CPU/RAM, some services disabled |
docker-compose.override.yml |
Local dev — picked up automatically by Docker Compose |
Memory Reservation > Limit Error Across Override Files
A related Docker Compose gotcha: Docker enforces memory limit >= memory reservation strictly at container start time. This breaks silently when override files set smaller limits without redefining reservations.
Error Message
Error response from daemon: Minimum memory limit can not be less than memory reservation limit
The Conflict
# docker-compose.prod.yml — sets large reservations
services:
mongodb:
deploy:
resources:
reservations:
memory: 2G
# docker-compose.optical-dev.yml — reduces limits but forgets reservations
services:
mongodb:
deploy:
resources:
limits:
memory: 1G # ERROR: 1G limit < 2G reservation inherited from prod
# reservations: not redefined — Docker inherits 2G from prod file
Fix: Redefine Reservations in Every Override That Reduces Limits
# docker-compose.optical-dev.yml
services:
mongodb:
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512M # must be <= limit
The rule: every override layer that changes memory limits must also set reservations ≤ new limit.
Related Concepts
- wiki/architecture/cloud-run-jobs-celery — why optical-dev uses this pattern for heavy workers
- wiki/architecture/optical-dev-server-deploy — optical-dev server constraints and deployment pattern
Sources
- daily/2026-04-29.md — session 20:29,
cpus: '4.0'breaking on 2-CPU optical-dev server - daily/2026-04-30.md — session 12:11, memory reservation > limit error in override files