What's Actually Happening
Docker container is killed by the OOM (Out of Memory) killer when it exceeds its memory limit. The container exits unexpectedly with exit code 137, causing service disruption.
The Error You'll See
Container exit code 137:
```bash $ docker ps -a
CONTAINER ID IMAGE COMMAND STATUS PORTS abc123 my-app "node app" Exited (137) 5 seconds ago
# Exit code 137 = 128 + 9 (SIGKILL from OOM killer) ```
Docker events:
```bash $ docker events --filter container=my-container
2026-04-16T01:08:00Z container kill abc123 (signal=9, exitCode=137) 2026-04-16T01:08:00Z container die abc123 (exitCode=137) ```
System logs:
```bash $ dmesg | grep -i "killed process"
[12345.678901] Killed process 1234 (node) total-vm:2097152kB, anon-rss:1048576kB ```
Why This Happens
- 1.Memory limit too low - Application needs more memory
- 2.Memory leak - Application leaking memory over time
- 3.No swap configured - No overflow for memory spikes
- 4.Heavy workload - Processing larger than expected data
- 5.Multiple processes - Sidecar containers consuming memory
- 6.JVM heap issues - Java container not configured for container limits
Step 1: Check Container Memory Usage
```bash # Check running container stats docker stats
# Output: CONTAINER CPU % MEM USAGE / LIMIT MEM % my-container 5.0% 500MiB / 512MiB 97.6% # Near limit!
# Check specific container docker stats my-container --no-stream
# Check container memory limit docker inspect my-container --format '{{.HostConfig.Memory}}'
# Check memory and swap limit docker inspect my-container --format 'Memory: {{.HostConfig.Memory}}, Swap: {{.HostConfig.MemorySwap}}'
# Check OOM killed flag docker inspect my-container --format '{{.State.OOMKilled}}'
# Check exit code docker inspect my-container --format '{{.State.ExitCode}}'
# View container events docker events --filter container=my-container --since 1h ```
Step 2: Check System Memory and OOM
```bash # Check host memory free -h
# Check system OOM kills dmesg | grep -i "out of memory" | tail -20
# Check for killed processes dmesg | grep -i "killed process"
# Check cgroup memory cat /sys/fs/cgroup/memory/docker/<container-id>/memory.usage_in_bytes cat /sys/fs/cgroup/memory/docker/<container-id>/memory.limit_in_bytes
# Check memory stats cat /sys/fs/cgroup/memory/docker/<container-id>/memory.stat | head -20
# Check for OOM score cat /sys/fs/cgroup/memory/docker/<container-id>/memory.oom_control ```
Step 3: Increase Memory Limit
```bash # Run with more memory docker run -d --name my-container --memory="1g" my-image
# With memory and swap docker run -d --name my-container \ --memory="1g" \ --memory-swap="2g" \ my-image
# Allow swap = memory + swap amount # memory-swap = memory + swap # --memory="1g" --memory-swap="2g" means 1GB RAM + 1GB swap
# Disable swap limit docker run -d --name my-container \ --memory="1g" \ --memory-swap="-1" \ my-image
# In docker-compose.yml: services: my-app: image: my-image deploy: resources: limits: memory: 1G reservations: memory: 512M
# Update running container (requires recreating) docker-compose up -d --force-recreate ```
Step 4: Configure Memory Swappiness
```bash # Set swappiness (0-100, lower = less swap usage) docker run -d --name my-container \ --memory="1g" \ --memory-swappiness="60" \ my-image
# Swappiness values: # 0 = never swap unless absolutely necessary # 60 = default # 100 = swap aggressively
# In docker-compose.yml: services: my-app: mem_swappiness: 60
# Disable OOM killer for critical container (use carefully) docker run -d --name my-container \ --memory="1g" \ --oom-kill-disable=true \ my-image
# WARNING: Disabling OOM kill can cause system instability ```
Step 5: Configure Java Containers
```bash # Java applications need special memory configuration
# WRONG: JVM doesn't know container limits java -Xmx2g -jar app.jar
# CORRECT: Use container-aware JVM (Java 10+) java -XX:MaxRAMPercentage=75.0 -jar app.jar
# Or Java 8u191+ with flags: java -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -jar app.jar
# In Dockerfile: FROM openjdk:17 ENV JAVA_OPTS="-XX:MaxRAMPercentage=75.0" CMD ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]
# For older Java versions: ENV JAVA_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2"
# In docker-compose: environment: - JAVA_OPTS=-XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0 ```
Step 6: Configure Node.js Containers
```bash # Node.js memory configuration
# Set heap size docker run -d --name my-container \ --memory="1g" \ -e NODE_OPTIONS="--max-old-space-size=768" \ my-image
# In Dockerfile: ENV NODE_OPTIONS="--max-old-space-size=768"
# In docker-compose: environment: - NODE_OPTIONS=--max-old-space-size=768
# Use 75% of container memory for Node heap # If container has 1GB, use 768MB for heap ```
Step 7: Monitor Memory Usage
```bash # Create monitoring script cat << 'EOF' > monitor_docker_memory.sh #!/bin/bash echo "=== Container Memory Usage ===" docker ps --format "table {{.Names}}\t{{.Image}}" | head -1 docker ps --format "{{.Names}}\t{{.Image}}" | while read name image; do if [ "$name" != "NAMES" ]; then stats=$(docker stats $name --no-stream --format "{{.MemUsage}}") echo "$name\t$image\t$stats" fi done
echo "" echo "=== Recent OOM Kills ===" dmesg | grep -i "killed process" | tail -5
echo "" echo "=== Host Memory ===" free -h EOF
chmod +x monitor_docker_memory.sh
# Continuous monitoring watch -n 5 ./monitor_docker_memory.sh
# Use ctop for better monitoring pip install ctop ctop ```
Step 8: Optimize Application Memory
```bash # Profile application memory usage
# For Node.js: node --inspect app.js # Chrome DevTools > Memory > Take heap snapshot
# For Python: pip install memory_profiler python -m memory_profiler script.py
# For Java: java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xlog:gc* app.jar # Or use VisualVM, JProfiler
# For Go: # Use pprof import _ "net/http/pprof" # Then: go tool pprof http://localhost:6060/debug/pprof/heap
# Check for memory leaks # Run under load and monitor memory growth ```
Step 9: Use Health Checks and Restart Policies
```yaml # docker-compose.yml with health check services: my-app: image: my-image deploy: resources: limits: memory: 1G healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s restart: unless-stopped
# Restart policies: # - no: Never restart # - on-failure: Restart on failure # - always: Always restart # - unless-stopped: Restart unless manually stopped
# Limit restart attempts restart: on-failure:5 ```
Step 10: Set Up Alerts for OOM
```bash # Prometheus alert rule for OOM cat << 'EOF' > oom_alert.yml groups: - name: container_oom rules: - alert: ContainerOOMKilled expr: increase(container_oom_events_total[5m]) > 0 for: 1m labels: severity: critical annotations: summary: "Container OOM killed" description: "Container {{ $labels.name }} was OOM killed"
- alert: ContainerMemoryHigh
- expr: container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.9
- for: 5m
- labels:
- severity: warning
- annotations:
- summary: "Container memory usage > 90%"
- EOF
# Use Docker event monitoring docker events --filter 'event=oom' --format '{{.Time}} {{.Actor.Attributes.name}} OOM killed' ```
Docker Container OOM Checklist
| Check | Command | Expected |
|---|---|---|
| Container status | docker ps -a | Running, not exited 137 |
| Memory usage | docker stats | < 80% of limit |
| Memory limit | docker inspect | Sufficient for app |
| OOM killed | inspect .State.OOMKilled | false |
| Host memory | free -h | Available |
| Swap available | docker inspect | Configured if needed |
Verify the Fix
```bash # After increasing memory or optimizing application
# 1. Check container running docker ps | grep my-container // Status: Up, not Exited (137)
# 2. Monitor memory usage docker stats my-container --no-stream // MEM USAGE < 80% of LIMIT
# 3. Check for OOM kills docker inspect my-container --format '{{.State.OOMKilled}}' // false
# 4. Check system logs dmesg | grep -i "killed process" // No recent OOM kills
# 5. Test under load # Run load test, verify container stays running
# 6. Monitor over time watch -n 10 'docker stats --no-stream' // Memory stable, not growing ```
Related Issues
- [Fix Docker Container Restarting Loop](/articles/fix-docker-container-restarting-loop)
- [Fix Docker Container Not Starting](/articles/fix-docker-container-not-starting)
- [Fix Docker Disk Space Full](/articles/fix-docker-disk-space-full)