Docker Composeలో OOM ఆపే memory limits ఎలా సెట్ చేయాలి
VPSలో ఒక container మొత్తం RAMను ఖర్చు చేయకుండా Docker Composeలో deploy.resources, mem_limit, CPU, swap పరిమితులు సెట్ చేయండి. exit 137 కారణం, sizing తెలుసుకోండి.
Docker Compose memory limit ఏమి చేస్తుంది
Docker Compose memory limit అనేది ఒక container యొక్క cgroup పై Linux kernel విధించే గరిష్ఠ పరిమితి. cgroup అనేది process సమూహం వినియోగించే వనరులను కొలిచే kernel feature. Service పై deploy.resources.limits.memory సెట్ చేస్తే, ఆ container మీరు పేర్కొన్న పరిమాణం కంటే ఎక్కువ memory ఎప్పటికీ ఉపయోగించలేదు. అది ఆ పరిమితిని మించేందుకు ప్రయత్నించినప్పుడు, kernel container లోని ఒక process ను terminate చేస్తుంది. సాధారణంగా container code 137 తో exit అవుతుంది.
ఈ విషయం ముఖ్యంగా VPS లో ప్రాధాన్యమైనది. VPS లో RAM పరిమితంగా ఉంటుంది, అదనపు host memory అందుబాటులో ఉండదు. Memory leak లేదా తప్పు query ఉన్న ఒక container 8GB server లోని ఖాళీ memory మొత్తం వినియోగించవచ్చు. అప్పుడు kernel సమస్యకు అత్యంత బాధ్యత వహిస్తుందని భావించిన process ను terminate చేస్తుంది. అది సమస్యకు కారణమైన container కాకుండా database లేదా మీ SSH session కూడా కావచ్చు. Limits ఉపయోగిస్తే మొత్తం server outage బదులుగా ఒక service మాత్రమే restart అవుతుంది.
services:
app:
image: ghcr.io/example/app:1.4
deploy:
resources:
limits:
cpus: "1.5"
memory: 1g
reservations:
memory: 256mదాన్ని వర్తింపజేసి, limit అమల్లో ఉందని నిర్ధారించండి:
docker compose up -d
docker stats --no-streamMEM USAGE / LIMIT column లో సాధారణంగా 142MiB / 1GiB వంటి విలువ కనిపించాలి. Limit column లో మొత్తం host RAM కనిపిస్తే, setting వర్తించలేదు. అది వర్తించే వరకు ఈ guide లోని మిగతా సూచనలు ఉపయోగపడవు. Compose file మీకు కొత్తగా ఉంటే, VPS కోసం Docker Compose ప్రాథమికాలు ఈ file layout పై మరింత వివరణ ఇస్తాయి.
deploy.resources.limits లేదా mem_limit: ఏది వర్తిస్తుంది
ఒకే భావానికి రెండు రకాల notationలు ఉన్నాయి. అందుకే ఇది గందరగోళంగా ఉంటుంది.
mem_limit, mem_reservation, memswap_limit, cpus మరియు cpu_shares పాత Compose file formats నుంచి వచ్చిన top-level service keys. deploy.resources Swarm schema నుంచి వచ్చింది. ప్రస్తుతం ఇది Compose Specification లో భాగం. ఇదే format ను docker compose ఇప్పుడు చదువుతుంది.
ఒకే host పై రెండూ పనిచేస్తాయి. Swarm cluster లేకపోయినా, docker compose plugin మీరు docker compose up నడిపినప్పుడు deploy.resources.limits మరియు deploy.resources.reservations ను వర్తింపజేస్తుంది. ఈ plugin ప్రస్తుతం v5 series లో ఉంది. 2026-10-06 న పరిశీలించినప్పుడు v5.6.0 తాజా stable release గా ఉంది. పాత Compose file format versions తో గందరగోళం రాకుండా v2 నుంచి నేరుగా v5 కు మారింది. అందువల్ల 3 మరియు 4 ను దాటేసింది. v5 లోని ఏ release కూడా resource limits నిర్వహణ విధానాన్ని మార్చలేదు. deploy block లోని Swarm-only అంశాలు మిగిలిన keys: mode, placement, update_config మరియు endpoint_mode. ఇవి docker stack deploy కు అర్థవంతమైనవి. docker compose up వీటిని విస్మరిస్తుంది. కాబట్టి "deploy కు Swarm అవసరం" అనే సాధారణ సలహా resources subsection కు వర్తించదు. దాన్ని అనుసరిస్తే మీ services కు ఎలాంటి limit ఉండదు.
ప్రతి project కు ఒక notation మాత్రమే ఎంచుకోండి. ఒకే service పై mem_limit: 512m మరియు deploy.resources.limits.memory: 1g రెండింటినీ రాస్తే, file ను చూసిన వెంటనే అర్థం చేసుకోవడం కష్టం అవుతుంది. ఏ విలువ వర్తించిందో ఊహించకుండా daemon ను అడగండి:
docker inspect --format '{{.HostConfig.Memory}} {{.HostConfig.MemoryReservation}} {{.HostConfig.NanoCpus}}' app-1Memory values bytes లో ఉంటాయి. అందువల్ల 1g ను 1073741824 గా చూపిస్తుంది. CPU విలువ nano CPUs లో ఉంటుంది. అందువల్ల 1.5 ను 1500000000 గా చూపిస్తుంది. ఏ field లోనైనా 0 ఉంటే limit సెట్ కాలేదని అర్థం. Docker అంగీకరించే కనిష్ఠ memory limit 6m. దాని కంటే తక్కువ limit ఇస్తే container ప్రారంభం కాదు.
container పరిమితిని చేరుకున్నప్పుడు ఏమి జరుగుతుంది
container నెమ్మదించదు. అది ఆగిపోతుంది.
ఒక process ఒక page కోసం అభ్యర్థించినప్పుడు, cgroup ఇప్పటికే దాని memory.max వద్ద ఉంటే, kernel ముందుగా ఆ cgroup లో సాధ్యమైనంత memory ను reclaim చేస్తుంది: ముందుగా clean page cache, తరువాత swap చేయగల pages. Reclaim ద్వారా తగినంత memory విడుదల కాకపోతే, cgroup OOM (out of memory) killer container లోని ఒక process ను ఎంచుకుని దానికి SIGKILL పంపుతుంది. Container యొక్క PID 1 ను kill చేస్తే container ఆగిపోతుంది. Exit code 137 అంటే 128 కి signal 9 కలిపిన విలువ మాత్రమే. అందువల్ల 137 అనేది ఏ SIGKILL కైనా కనిపించే గుర్తు; అది ఒక్కటే OOM జరిగినట్లు నిర్ధారించదు.
docker compose ps -a
docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' app-1true 137 అనేది OOM kill. false 137 అంటే మరేదో SIGKILL పంపింది. సాధారణ కారణం, app SIGTERM ను పట్టించుకోకపోవడంతో docker compose stop దాని పది సెకన్ల grace period ను చేరుకోవడం. ఈ తేడా వల్ల గంటల సమయం ఆదా అవుతుంది, ఎందుకంటే ఈ రెండు సమస్యలకు పరస్పర సంబంధం లేదు.
ఈ సంఘటనను మరో రెండు చోట్ల నమోదు చేస్తారు. daemon ను ప్రత్యక్షంగా monitor చేయండి:
docker events --filter event=oomతర్వాత kernel log ను చదవండి. Restart తర్వాత కూడా మిగిలే record ఇదే:
sudo dmesg -T | grep -i -E 'memory cgroup out of memory|killed process'cgroup kill జరిగినప్పుడు Memory cgroup out of memory: Killed process 24713 (node) తో ప్రారంభమయ్యే line కనిపిస్తుంది. Memory cgroup prefix లేని line host OOM ను సూచిస్తుంది. అంటే machine లోని RAM మొత్తం అయిపోయిందన్నమాట. Limits నిరోధించాల్సిన failure ఇదే. కాబట్టి అది కనిపిస్తే, మీ limits మొత్తం చాలా ఎక్కువగా ఉన్నాయని లేదా కొన్ని services కు అసలు limit లేదని అర్థం.
restart: unless-stopped ఉన్నప్పుడు OOM loop ను సులభంగా గుర్తించలేరు, ఎందుకంటే service ఆగిన ఒక సెకను తర్వాత docker compose ps లో మళ్లీ up గా కనిపిస్తుంది. Uptime column మరియు restart count ను పరిశీలించండి. అలాగే app ను unhealthy గా నివేదించే healthcheck తో limit ను కలిపి ఉపయోగించండి. అప్పుడు నిరంతరం ఆగిపోతున్న container ను మీరు ప్రత్యక్షంగా చూడకపోయినా గుర్తించవచ్చు.
Reservation ఒక సూచన మాత్రమే; limit నియమం
reservations.memory (పాత mem_reservation) ఒక soft floor. Hostపై contention లేదా తక్కువ memory ఉందని daemon గుర్తించినప్పుడు ఇది అమలయ్యే soft limit అని Docker వివరిస్తుంది. ఇది container ఆ పరిమితిని మించకుండా ఎప్పుడూ ఆపదు. Container memory అడిగే సమయంలో అది ఖాళీగా ఉంటుందని కూడా ఎప్పుడూ హామీ ఇవ్వదు. Reservation కంటే ఎక్కువ memory ఉపయోగిస్తున్న containers నుంచి ముందుగా memory reclaim చేయాలని ఇది kernelకు ప్రాధాన్యతను మాత్రమే ఇస్తుంది.
అందువల్ల reservation ఒక్కటే ఏదినీ రక్షించదు. ఒత్తిడి సమయంలో ప్రత్యేక శ్రద్ధతో నిర్వహించాలనుకునే serviceను గుర్తించడానికి దీన్ని ఉపయోగించండి. భద్రత కోసం limitపై ఆధారపడండి. Reservationను limit కంటే తక్కువగా ఉంచండి. లేకపోతే container ప్రారంభం కాదు: Docker Minimum memory limit can not be less than memory reservation limit తో configను తిరస్కరిస్తుంది.
Swap లెక్కింపు, వాస్తవ పరిస్థితి
చాలా VPS images లో swap file ఏదీ ఉండదు. swapon --show మరియు free -h ను అమలు చేయండి. మొత్తం swap విలువ zero అయితే, కింద ఉన్న swap సంబంధిత settings ఏవీ పనిచేయవు. అప్పుడు మీ memory limit పూర్తిగా RAM పరిమితిగానే ఉంటుంది.
memswap_limit అనేది swap పరిమాణం కాదు. ఇది memory మరియు swap కలిపిన మొత్తం. mem_limit: 1g మరియు memswap_limit: 2g తో container కు 1GB RAM మరియు 1GB swap లభిస్తాయి. రెండు values ను సమానంగా సెట్ చేస్తే container కు swap ఉండదు. mem_limit ను సెట్ చేసి memswap_limit ను unset గా ఉంచితే, container మళ్లీ తన memory limit పరిమాణం వరకు swap ఉపయోగించగలదు.
Ubuntu 24.04 మరియు Debian 13 డిఫాల్ట్గా cgroup v2 ను ఉపయోగిస్తాయి. ఇందులో swap ప్రత్యేక counter (memory.swap.max) గా ఉంటుంది. అదనపు setup లేకుండానే ఇది పనిచేస్తుంది. Your kernel does not support swap limit capabilities అనే పాత message, swapaccount=1 లేకుండా boot చేసిన cgroup v1 hosts నుంచి వస్తుంది. అలాంటి hosts లో memory limit అమలవుతుంది, కానీ swap భాగం పట్టించుకోబడదు.
swap వల్ల కలిగే ప్రయోజనాన్ని వాస్తవికంగా అంచనా వేయండి. ఇది OOM kill ను నెమ్మదిగా చేస్తుంది, కానీ అది సంభవించే అవకాశాన్ని తగ్గించదు. ఎందుకంటే memory leak ఉన్న process RAM ను నింపినట్లే swap ను కూడా నింపుతుంది. అదే సమయంలో shared VPS storage పై swap ను అధికంగా ఉపయోగించే container, ఆ server లోని ఇతర సేవలన్నింటినీ నెమ్మదింపజేస్తుంది. latency కు సున్నితమైన సేవలకు swap లేకుండా సరైన limit సెట్ చేయడం వల్ల వైఫల్యం వేగంగా మరియు మరింత ఊహించదగిన విధంగా జరుగుతుంది.
మెమరీ వినియోగం వాస్తవం కంటే ఎక్కువగా కనిపించడానికి కారణం
docker stats లోని MEM USAGE గణాంకంలో page cache కూడా ఉంటుంది. అందువల్ల పెద్ద ఫైళ్లను చదివే container దాని limit వైపు పెరిగి, అక్కడే స్థిరంగా ఉంటుంది. ఇది సాధారణ ప్రవర్తన. ఇది memory leak కాదు. ఎందుకంటే OOM killer ను పిలిచేలోపే clean cache ను తిరిగి వినియోగించుకోవచ్చు. self-hosted Jellyfin media server వంటి సేవ ఈ కారణంగానే తన గరిష్ఠ పరిమితికి శాశ్వతంగా దగ్గరగా ఉన్నట్లు కనిపిస్తుంది.
Container లోపల cache మరియు వాస్తవ working set గా ఆ సంఖ్యను విడగొట్టండి:
docker compose exec app grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat
docker compose exec app cat /sys/fs/cgroup/memory.eventsanon అనేది anonymous memory. ఇది తొలగించలేని working set. file అనేది page cache. దీన్ని తిరిగి వినియోగించుకోవచ్చు. మీ limit ను మొత్తం విలువ ఆధారంగా కాకుండా anon కు కొంత అదనపు మార్జిన్ జోడించి నిర్ణయించండి. memory.events ఫైల్ దీనిని స్పష్టంగా నిర్ధారిస్తుంది: oom_kill counter సున్నా కంటే ఎక్కువగా ఉంటే, ఈ container ప్రారంభమైన తర్వాత kernel ఇందులో ఏదో ఒకదాన్ని terminate చేసింది. max counter పెరుగుతూ ఉంటే, container ప్రస్తుతం తన గరిష్ఠ పరిమితి వద్ద నిలిపివేయబడుతోంది. రెండు commands పనిచేయాలంటే image లో shell మరియు coreutils ఉండాలి. అందువల్ల distroless లేదా scratch image లో ఇవి విఫలమవుతాయి.
8GB VPS పై పరిమాణ పరిమితులు
అప్లికేషన్ల నుంచి కాకుండా host నుంచి ప్రారంభించండి. 8GB VPSలో kernel, Docker daemon, sshd, journald మరియు మీ login shell కోసం సుమారు 1GB విడిచిపెట్టండి. దాంతో కేటాయించడానికి సుమారు 7GB మిగులుతుంది. ప్రతి container పరిమితుల మొత్తం దీనికంటే తక్కువగా ఉండాలి. రెండు సేవలు ఒకేసారి గరిష్ఠ వినియోగానికి చేరుకునే రోజు వరకు overcommit సరిగానే పనిచేయవచ్చు.
8GB సర్వర్పై ఉపయోగించగల విభజన:
- Reverse proxy: 128m limit. ఇది చిన్న process. ఇంత కఠినమైన limit runaway config reload ను వెంటనే గుర్తిస్తుంది.
- PostgreSQL: 2g limit. Database config లో
shared_buffersను సుమారు 512MBగా సెట్ చేయండి. - Application container: 1g limit.
- Background worker: 512m limit.
- Media లేదా file service: 2g limit. ఇందులో ఎక్కువ భాగం page cache కోసం ఉపయోగించబడుతుంది.
ఈ సంఖ్యలను మీ స్వంత stackలో నేరుగా ఉపయోగించవద్దు. నిజమైన load కింద సేవలను ఒక రోజు నడపండి. docker stats ను monitor చేయండి. ప్రతి container కోసం గరిష్ఠ anon విలువను నమోదు చేసి, headroom కోసం దానికి సుమారు సగం అదనంగా జోడించండి. చాలా కఠినంగా సెట్ చేసిన limit, limit లేకపోవడం కంటే అధ్వాన్నం. సాధారణ network traffic పెరుగుదల సమయంలో ఆరోగ్యంగా ఉన్న సేవను అది నిలిపివేస్తుంది.
ఒక ముఖ్యమైన సమస్యకు ప్రత్యేకంగా గమనించాలి. Limit గురించి runtimes కు తెలియజేయకపోతే, వాటిలో చాలా వరకు దాన్ని గుర్తించవు. PostgreSQL shared_buffers మరియు work_mem పరిమాణాలను తన container limit కంటే ఎక్కువగా సెట్ చేసి, చివరకు killed స్థితికి చేరవచ్చు. JVM (Java virtual machine) host RAM ఆధారంగా కాకుండా cgroup limit ఆధారంగా heap పరిమాణాన్ని నిర్ణయించడానికి -XX:MaxRAMPercentage=75 అవసరం. Node.js కు megabytesలో --max-old-space-size అవసరం. దీన్ని container limit కంటే తక్కువగా సెట్ చేయాలి. లేకపోతే garbage collector heap పెరుగుతూనే ఉండేలా చేసి, kernel జోక్యం చేసుకునే వరకు తీసుకెళ్తుంది. Ollamaలో కూడా ఇదే పరిస్థితి, కానీ అక్కడ వేరే knob ఉంటుంది. num_ctx పెంచితే KV cache వందల megabytes మేర పెరుగుతుంది; దాంతో దీర్ఘమైన prompt మధ్యలో container నిలిచిపోతుంది. cgroup చర్చించదు. అది process ను killed చేస్తుంది.
CPU limits పూర్తిగా భిన్నంగా పనిచేస్తాయి
cpus: "1.5" అంటే ఒక core సామర్థ్యంలో 150%. ఇది CFS (completely fair scheduler) quotaగా అమలు చేయబడుతుంది. ప్రతి 100ms వ్యవధిలో containerకు 150ms CPU సమయం లభిస్తుంది. ఈ సమయం దాని అన్ని threads మధ్య భాగస్వామ్యం అవుతుంది. ఆ సమయం పూర్తయినప్పుడు, తదుపరి వ్యవధి వరకు kernel దాన్ని వేచి ఉండేలా చేస్తుంది.
ఇదే ముఖ్యమైన తేడా. Memory limit ను మించిన container kill అవుతుంది. CPU limit ను మించిన container throttle చేయబడుతుంది, కానీ నెమ్మదిగా కొనసాగుతుంది. అందువల్ల CPU limit ను కొంత కఠినంగా సెట్ చేయడం సురక్షితం. Memory limit కు మాత్రం అదనపు headroom అవసరం.
cpu_shares వేరే సాధనం. ఇది relative weight. CPUs వాస్తవంగా పూర్తిగా వినియోగంలో ఉన్నప్పుడు మాత్రమే దీనికి ప్రభావం ఉంటుంది. 1024 మరియు 512 shares ఉన్న రెండు containers busy core ను సుమారు two-to-one నిష్పత్తిలో పంచుకుంటాయి. Idle systemలో అయితే ఏ containerకూ పరిమితి ఉండదు. Services ప్రాధాన్యతను క్రమబద్ధీకరించడానికి shares ను ఉపయోగించండి. వాస్తవ ceiling అవసరమైనప్పుడు cpus ను ఉపయోగించండి. ఉదాహరణకు, ప్రతి రాత్రి జరిగే transcode job మీ web serverకు CPU కొరత కలిగించకుండా ఆపడానికి ఇది ఉపయోగపడుతుంది.
FAQ
Docker Swarm లేకుండా deploy.resources.limits పనిచేస్తుందా?
అవును. ఒకే host పై docker compose up నడిపినప్పుడు Docker Compose, docker compose plugin (ప్రస్తుతం దీని v5 line అందుబాటులో ఉంది), deploy.resources.limits మరియు deploy.resources.reservations ను అమలు చేస్తుంది. పరిమితి bytes లో ముద్రించబడుతుంది. ఎలాంటి పరిమితి వర్తించకపోతే 0 ముద్రించే docker inspect --format '{{.HostConfig.Memory}}' <container> తో దీన్ని నిర్ధారించండి. Swarm నిజంగా అవసరమైన deploy లోని keys mode, placement, update_config మరియు endpoint_mode.
Docker Compose లో exit code 137 అంటే ఏమిటి?
ప్రధాన process SIGKILL ను స్వీకరించిందని అర్థం, ఎందుకంటే 137 అనేది 128కు signal 9ను కలిపిన విలువ. సాధారణ కారణం kernel OOM killer. అయితే ఒక app SIGTERM ను పట్టించుకోనప్పుడు shutdown timeout వల్ల కూడా ఇదే code వస్తుంది. ఈ రెండింటిని వేరు చేయడానికి docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' <container> నడపండి. true 137 memory kill ను సూచిస్తుంది, false 137 మాత్రం సూచించదు.
mem_limit లేదా deploy.resources.limits.memory ను సెట్ చేయాలా?
docker compose తో రెండింటిలో ఏదైనా పనిచేస్తుంది. deploy.resources.limits.memory ప్రస్తుత Compose Specification రూపం. కొత్త file కోసం అదే మెరుగైన default. మీ file లో మిగతా భాగం ఇప్పటికే పాత top-level keys ను ఉపయోగిస్తే mem_limit ను ఉంచండి. ఒకే service పై రెండింటినీ సెట్ చేస్తే file చదవడం మాత్రమే కష్టమవుతుంది. కాబట్టి ఒకదాన్ని ఎంచుకుని docker inspect తో ఫలితాన్ని నిర్ధారించండి.
నా container దాని పూర్తి memory limit వరకు ఉపయోగిస్తున్నప్పటికీ ఎందుకు kill కావడం లేదు?
docker stats లోని usage figure లో page cache కూడా ఉంటుంది. Memory pressure వచ్చినప్పుడు kernel OOM kill ను ప్రారంభించకుండా page cache ను తొలగిస్తుంది. docker compose exec <service> grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat నడిపి anon value ను పరిశీలించండి. Reclaim చేయలేని working set ఇదే. తక్కువ anon value పక్కన ఎక్కువ file value కనిపిస్తే, అది disk input మరియు output చేస్తున్న container. చనిపోవడానికి సిద్ధంగా ఉన్న container కాదు.
8GB VPS లో ఎంత RAM ను కేటాయించకుండా ఉంచాలి?
Kernel, Docker daemon, sshd, journald మరియు మీ స్వంత shell కోసం సుమారు 1GB ఉంచండి. తరువాత అన్ని container limits మొత్తాన్ని మిగిలిన 7GB కంటే తక్కువగా ఉంచండి. నిజమైన load లో ఒక రోజు ప్రతి container యొక్క గరిష్ఠ anon value ను monitor చేయండి. సంఖ్యలను ఖరారు చేసే ముందు దీన్ని చేయండి. మొత్తం పరిమితిని నింపాల్సిన లక్ష్యంగా కాకుండా budget గా పరిగణించండి.