Runtime Performance Optimization
By default, a single container can consume all host CPU and memory, starving other containers. Setting resource limits prevents one misbehaving container from taking down your entire host.
Resource Limits
Memory Limits
# Limit container to 512 MB of RAM
docker run -d --memory=512m my-app:1.0.0
# Memory + swap (set equal to disable swap)
docker run -d --memory=512m --memory-swap=512m my-app:1.0.0
In Compose:
services:
api:
image: my-api:1.0.0
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
OOM Killer
If a container exceeds its memory limit, Docker kills it immediately (OOM). Check with:
docker inspect CONTAINER --format '{{.State.OOMKilled}}'
CPU Limits
# Limit to 1.5 CPU cores
docker run -d --cpus=1.5 my-app:1.0.0
# CPU shares (relative weight, default 1024)
docker run -d --cpu-shares=512 my-app:1.0.0
In Compose:
services:
api:
image: my-api:1.0.0
deploy:
resources:
limits:
cpus: "1.5"
reservations:
cpus: "0.5"
| Flag | Behavior | Use Case |
|---|---|---|
--cpus=N | Hard limit to N cores | Prevent CPU monopoly |
--cpu-shares=N | Relative weight (only under contention) | Fair sharing |
--memory=N | Hard limit, OOM kill if exceeded | Prevent memory monopoly |
--memory-reservation=N | Soft limit, best-effort | Planning, not enforcement |
Monitoring Resources
Live Monitoring
# Live resource usage for all containers
docker stats
# Custom format
docker stats --format 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}'
# One-shot snapshot (no streaming)
docker stats --no-stream
Historical Data
# Check if container was OOM-killed
docker inspect CONTAINER --format '{{.State.OOMKilled}}'
# Check restart count (high = crash loop)
docker inspect CONTAINER --format '{{.RestartCount}}'
# Check current resource config
docker inspect CONTAINER --format '{{json .HostConfig.Memory}}'
docker inspect CONTAINER --format '{{json .HostConfig.NanoCpus}}'
Process Limits
Prevent fork bombs and runaway process spawning:
docker run -d --pids-limit=256 my-app:1.0.0
In Compose:
services:
api:
image: my-api:1.0.0
pids_limit: 256
Restart Policies
Configure how Docker handles container crashes:
| Policy | Behavior | Use Case |
|---|---|---|
no | Never restart (default) | One-off tasks |
on-failure | Restart only on non-zero exit | Most services |
on-failure:5 | Restart on failure, max 5 attempts | Prevent infinite loops |
unless-stopped | Always restart unless explicitly stopped | Production services |
always | Always restart, even after reboot | Critical infrastructure |
services:
api:
image: my-api:1.0.0
restart: unless-stopped
Optimizing Container Startup
Use Health Checks to Signal Readiness
services:
api:
image: my-api:1.0.0
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
The start_period gives the container time to initialize before health checks begin failing.
Graceful Shutdown
Ensure your application handles SIGTERM properly. Docker sends SIGTERM on stop, then SIGKILL after the timeout (default 10 seconds):
# Give the app 30 seconds to shut down gracefully
docker stop -t 30 my-app
Key Takeaways
- Set memory and CPU limits to prevent any single container from monopolizing host resources.
- Monitor with
docker statsand checkOOMKilledafter unexplained restarts. - Use
--pids-limitto prevent fork bombs. - Set
restart: unless-stoppedfor production services. - Use
start_periodin health checks to avoid false failures during startup.
What's Next
- Continue to Storage Optimization.