SSD Nodes Learn RAM 8GB — $66/mwaka
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-01

Docker Compose: Weka Vikomo vya RAM Kuzuia OOM

Jifunze kuweka deploy.resources na mem_limit katika Docker Compose, kutafsiri exit 137, kudhibiti swap na CPU, na kupanga RAM kwa VPS bila OOM.

Kikomo cha kumbukumbu cha Docker Compose hufanya nini

Kikomo cha kumbukumbu cha Docker Compose ni kiwango cha juu kisichoweza kuzidiwa ambacho kernel ya Linux huweka kwenye cgroup (kikundi cha udhibiti, kipengele cha kernel kinachopima rasilimali za seti ya michakato) ya kontena moja. Weka deploy.resources.limits.memory kwenye huduma, na kontena hilo haliwezi kamwe kutumia zaidi ya nambari uliyoandika. Linapojaribu kufanya hivyo, kernel huua mchakato ndani ya kontena, na kwa kawaida kontena huacha kufanya kazi likiwa na msimbo wa 137.

Hili ni muhimu zaidi kwenye VPS, ambako RAM ni ya kudumu na hakuna kumbukumbu ya ziada ya host ya kukopa. Kontena moja lenye uvujaji wa kumbukumbu au query mbaya linaweza kutumia kila ukurasa wa kumbukumbu ulio huru kwenye mashine ya 8GB. Kisha kernel huua mchakato unaouona kuwa na athari kubwa zaidi, ambao mara nyingi huwa database au kikao chako cha SSH badala ya kontena lililosababisha tatizo. Vikomo hubadilisha hitilafu ya seva nzima kuwa tatizo la huduma moja inayowashwa upya.

services:
  app:
    image: ghcr.io/example/app:1.4
    deploy:
      resources:
        limits:
          cpus: "1.5"
          memory: 1g
        reservations:
          memory: 256m

Tekeleza hilo na uthibitishe kuwa kikomo kinafanya kazi:

docker compose up -d
docker stats --no-stream

Safu ya MEM USAGE / LIMIT inapaswa kuonyesha kitu kama 142MiB / 1GiB. Ikiwa safu ya kikomo inaonyesha RAM yote ya host, mpangilio haukutumika, na mwongozo huu hautasaidia hadi utumike. Ikiwa faili ya compose bado ni mpya kwako, misingi ya Docker Compose kwa VPS inaeleza muundo wa faili ambao mwongozo huu unategemea.

deploy.resources.limits au mem_limit: ni ipi hutumika

Kuna tahajia mbili za wazo lilelile, ndiyo maana jambo hili linachanganya.

mem_limit, mem_reservation, memswap_limit, cpus na cpu_shares ni funguo za huduma za kiwango cha juu zilizorithiwa kutoka miundo ya zamani ya faili za Compose. deploy.resources ilitoka kwenye schema ya Swarm na sasa ni sehemu ya Compose Specification, ambayo ndiyo muundo ambao docker compose husoma leo.

Zote hufanya kazi kwenye seva moja. Compose V2, programu-jalizi ya docker compose, hutumia deploy.resources.limits na deploy.resources.reservations unapoendesha docker compose up, bila kuwepo kwa cluster yoyote ya Swarm. Sehemu zinazotumika na Swarm pekee katika kizuizi cha deploy ni funguo nyingine: mode, placement, update_config na endpoint_mode zina maana kwa docker stack deploy na hupuuziwa na docker compose up. Kwa hiyo, ushauri wa kawaida kwamba "deploy inahitaji Swarm" si sahihi kwa sehemu ndogo ya resources. Kuufuata huacha huduma zako bila kikomo chochote.

Chagua tahajia moja kwa kila mradi. Kuandika mem_limit: 512m na deploy.resources.limits.memory: 1g kwenye huduma hiyo hiyo kunatoa faili ambayo ni vigumu kuielewa kwa kuisoma haraka. Badala ya kukisia ni namba ipi imetumika, iulize daemon:

docker inspect --format '{{.HostConfig.Memory}} {{.HostConfig.MemoryReservation}} {{.HostConfig.NanoCpus}}' app-1

Thamani za kumbukumbu hupimwa kwa bytes, kwa hiyo 1g huchapishwa kama 1073741824. CPU hupimwa kwa nano CPUs, kwa hiyo 1.5 huchapishwa kama 1500000000. 0 katika sehemu yoyote inamaanisha kuwa hakuna kikomo kilichowekwa. Kikomo cha chini kabisa cha kumbukumbu ambacho Docker inakubali ni 6m, na chini ya hapo container hukataa kuanza.

Kinachotokea kontena linapofikia kikomo

Kontena halipunguzi kasi. Linaacha kufanya kazi.

Mchakato unapoomba ukurasa wa kumbukumbu na cgroup tayari iko kwenye memory.max yake, kernel huanza kurejesha rasilimali inavyoweza ndani ya cgroup hiyo: kwanza akiba safi ya kurasa, kisha kurasa inazoweza kuhamishia kwenye swap. Ikiwa urejeshaji huo hautoi nafasi ya kutosha, kimaliza kumbukumbu cha OOM (out of memory) cha cgroup huchagua mchakato ndani ya kontena na kuutumia SIGKILL. Kuua PID 1 ya kontena humaliza kontena. Msimbo wa kutoka 137 ni 128 pamoja na signal 9, kwa hiyo 137 ni kiashiria cha SIGKILL yoyote, si uthibitisho wa OOM peke yake.

docker compose ps -a
docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' app-1

true 137 ni mauaji ya OOM. false 137 humaanisha kuwa kitu kingine kilituma SIGKILL, na sababu ya kawaida ni docker compose stop kufikia kipindi chake cha neema cha sekunde 10 kwa sababu programu ilipuuza SIGTERM. Tofauti hiyo huokoa saa nyingi, kwa sababu matatizo hayo mawili hayahusiani kabisa.

Maeneo mawili zaidi hurekodi tukio hilo. Fuatilia daemon moja kwa moja:

docker events --filter event=oom

Kisha soma logi ya kernel, ambayo ni rekodi inayobaki baada ya kuanzisha upya mfumo:

sudo dmesg -T | grep -i -E 'memory cgroup out of memory|killed process'

Mauaji ya cgroup huchapisha mstari unaoanza na Memory cgroup out of memory: Killed process 24713 (node). Mstari usio na kiambishi Memory cgroup ni OOM ya host, kumaanisha kuwa mashine yenyewe imeishiwa RAM. Hilo ndilo hitilafu ambalo vikomo vinakusudiwa kuzuia, kwa hiyo kuliona ni ishara kwamba jumla ya vikomo vyako ni kubwa mno, au kwamba baadhi ya huduma hazina kikomo kabisa.

Kwa restart: unless-stopped, mfululizo wa OOM unaweza kujificha kwa urahisi, kwa sababu huduma huonekana kuwa imeinuka katika docker compose ps sekunde moja baada ya kufa. Kagua safu ya uptime na idadi ya kuwashwa upya, kisha unganisha kikomo hicho na ukaguzi wa hali unaoripoti programu kuwa si salama ili kontena inayoendelea kufa ionekane bila wewe kuifuatilia.

Reservation ni kidokezo, kikomo ndicho kanuni

reservations.memory (mem_reservation ya zamani) ni kiwango cha chini kisicho cha lazima. Docker hukieleza kama kikomo laini kinachoamilishwa daemon inapotambua ushindani wa rasilimali au kumbukumbu ndogo kwenye host. Hakizuii kamwe container kuzidi kiwango hicho, wala hakihakikishi kamwe kwamba kumbukumbu itakuwa huru container inapoiomba. Huelekeza tu kernel ianze kurejesha kumbukumbu kutoka kwa containers zinazozidi reservation hiyo.

Kwa hiyo, reservation hailindi chochote yenyewe. Itumie kutambua service unayotaka ishughulikiwe kwa upendeleo wakati wa shinikizo, na tegemea limit kwa usalama. Weka reservation chini ya limit, la sivyo container haitaanza: Docker hukataa usanidi kwa Minimum memory limit can not be less than memory reservation limit.

Kuhesabu swap kwa usahihi

Picha nyingi za VPS hutolewa bila faili ya swap kabisa. Tekeleza swapon --show na free -h. Jumla ya swap ikiwa ni sifuri, mipangilio yote inayohusiana na swap hapa chini haitumiki, na kikomo chako cha kumbukumbu huwa kikomo halisi cha RAM.

memswap_limit si kiasi cha swap. Ni jumla ya kumbukumbu pamoja na swap. Kwa mem_limit: 1g na memswap_limit: 2g, kontena hupata 1GB ya RAM na 1GB ya swap. Kuweka thamani hizo mbili kuwa sawa huacha kontena bila swap kabisa. Kuweka mem_limit na kuacha memswap_limit bila kuwekwa huruhusu kontena kutumia swap hadi kufikia ukubwa wa kikomo chake cha kumbukumbu tena.

Ubuntu 24.04 na Debian 13 hutumia cgroup v2 kwa chaguo-msingi. Katika cgroup v2, swap ni kaunta tofauti (memory.swap.max), na mpangilio huu hufanya kazi bila usanidi wa ziada. Ujumbe wa zamani Your kernel does not support swap limit capabilities hutoka kwa wapangishaji wa cgroup v1 walioanzishwa bila swapaccount=1. Kwenye wapangishaji hao, kikomo cha kumbukumbu bado hutumika, lakini sehemu ya swap hupuuzwa.

Elewa kwa usahihi faida ya swap. Hufanya uondoaji wa mchakato kwa OOM uchelewe, lakini haupunguzi uwezekano wake, kwa sababu mchakato unaovuja kumbukumbu hujaza swap kwa urahisi sawa na RAM. Wakati huo huo, kontena inayotumia swap kupita kiasi kwenye hifadhi ya VPS inayoshirikiwa hupunguza kasi ya kila huduma nyingine kwenye seva hiyo. Kwa huduma yoyote inayohitaji ucheleweshaji mdogo, kikomo sahihi bila swap husababisha kushindwa kwa haraka na kwa kutabirika zaidi.

Kwa nini matumizi ya kumbukumbu yanaonekana kuwa mabaya kuliko yalivyo

Kielelezo cha MEM USAGE katika docker stats kinajumuisha akiba ya kurasa, kwa hiyo kontena linalosoma faili kubwa huongezeka hadi karibu na kikomo chake na kubaki hapo. Hili ni jambo la kawaida, na si uvujaji, kwa sababu akiba safi huachiliwa kabla ya OOM killer kuitwa. Huduma kama seva ya midia ya Jellyfin inayojipangisha itaonekana kuwa karibu kabisa na kikomo chake kwa sababu hiyo.

Gawanya nambari hiyo kuwa akiba na seti halisi ya kufanya kazi ukiwa ndani ya kontena:

docker compose exec app grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat
docker compose exec app cat /sys/fs/cgroup/memory.events

anon ni kumbukumbu isiyojulikana, yaani seti ya kufanya kazi ambayo haiwezi kuondolewa. file ni akiba ya kurasa, ambayo inaweza kuondolewa. Weka kikomo chako kwa kuzingatia anon pamoja na nafasi ya ziada, si jumla ya kumbukumbu. Faili ya memory.events huondoa utata kabisa: kaunta ya oom_kill iliyo juu ya sifuri inamaanisha kuwa kernel imeua kitu katika kontena hili tangu lilipoanzishwa, na kaunta ya max inayoongezeka inamaanisha kuwa kontena linazuiwa kwenye kikomo chake kwa sasa. Amri zote mbili zinahitaji shell na coreutils ndani ya image, kwa hiyo hushindwa kwenye image ya distroless au scratch.

Vikomo vya ugawaji wa rasilimali kwenye VPS ya 8GB

Anza na mwenyeji, si programu. Kwenye VPS ya 8GB, acha takriban 1GB kwa kernel, daemon ya Docker, sshd, journald na shell yako ya kuingia. Hivyo utabakiwa na takriban 7GB za kugawa, na jumla ya vikomo vya kila container inapaswa kubaki chini ya kiasi hicho. Kugawa rasilimali kupita kiasi hufanya kazi hadi siku ambayo huduma mbili zitafikia kilele kwa wakati mmoja.

Mgawanyo unaoweza kutumika kwenye mashine ya 8GB:

  • Reverse proxy: kikomo cha 128m. Ni mchakato mdogo, na kikomo hiki kikali hugundua mara moja usanidi wa reload unaozalisha matumizi kupita kiasi.
  • PostgreSQL: kikomo cha 2g, huku shared_buffers kikiwa kimewekwa takriban 512MB kwenye usanidi wa hifadhidata.
  • Container ya programu: kikomo cha 1g.
  • Worker wa chinichini: kikomo cha 512m.
  • Huduma ya media au faili: kikomo cha 2g, ambacho sehemu kubwa yake itakuwa page cache.

Usinakili nambari hizo moja kwa moja kwenye stack yako. Endesha huduma hizo chini ya mzigo halisi kwa siku moja, fuatilia docker stats, chukua thamani ya juu ya anon kwa kila container, kisha uongeze takriban nusu yake kama nafasi ya ziada. Kikomo kilichowekwa kuwa kidogo sana ni kibaya kuliko kutoweka kikomo, kwa sababu huua huduma iliyo salama wakati wa ongezeko la kawaida la network traffic.

Kuna mtego mmoja unaohitaji maelezo yake. Runtimes nyingi hazitambui kikomo hicho isipokuwa uziambie kukihusu. PostgreSQL itaweka shared_buffers na work_mem bila tatizo hadi kuvuka kikomo cha container yake, kisha itauawa. JVM (Java virtual machine) inahitaji -XX:MaxRAMPercentage=75 ili kuweka ukubwa wa heap kulingana na kikomo cha cgroup badala ya RAM ya host. Node.js inahitaji --max-old-space-size katika megabytes, ikiwa imewekwa chini ya kikomo cha container; vinginevyo garbage collector wake itaendelea kukuza heap hadi kernel iingilie kati. cgroup haijadiliani. Inaua.

Vikomo vya CPU hufanya kazi kwa njia tofauti kabisa

cpus: "1.5" inamaanisha 150% ya core moja, inayotekelezwa kama mgao wa CFS (completely fair scheduler). Kontena hupata 150ms za muda wa CPU katika kila kipindi cha 100ms, zikishirikiwa na nyuzi zake zote. Linapotumia muda huo wote, kernel hulilazimisha kusubiri hadi kipindi kinachofuata.

Huo ndio utofauti muhimu. Kontena linalozidi kikomo chake cha kumbukumbu linakomeshwa. Kontena linalozidi kikomo chake cha CPU linapunguziwa kasi na kuendelea kufanya kazi polepole zaidi. Kwa hiyo, ni salama kuweka kikomo cha CPU kwa kiwango cha juu, lakini kikomo cha kumbukumbu kinahitaji nafasi ya ziada.

cpu_shares ni zana tofauti: ni uzani wa kulinganisha unaokuwa muhimu tu CPU zinapokuwa zimejaa matumizi. Kontena mbili zenye shares za 1024 na 512 hugawana core yenye mzigo kwa uwiano wa takriban mbili kwa moja, na kwenye mashine isiyo na mzigo hakuna kati yazo inayozuiwa. Tumia shares kupanga huduma kulingana na umuhimu, na utumie cpus unapohitaji kikomo halisi, kwa mfano kuzuia kazi ya usimbaji wa video ya kila usiku isinyime server yako ya wavuti rasilimali.

FAQ

Je, deploy.resources.limits hufanya kazi bila Docker Swarm?

Ndiyo. Compose V2 hutumia deploy.resources.limits na deploy.resources.reservations unapoendesha docker compose up kwenye host moja. Thibitisha hilo kwa docker inspect --format '{{.HostConfig.Memory}}' <container>, ambayo huchapisha kikomo kwa baiti na kuchapisha 0 wakati hakuna kikomo kilichotumika. Vifunguo vilivyo ndani ya deploy vinavyohitaji Swarm kwa kweli ni mode, placement, update_config na endpoint_mode.

Msimbo wa kutoka 137 unamaanisha nini katika Docker Compose?

Unamaanisha kuwa mchakato mkuu ulipokea SIGKILL, kwa sababu 137 ni 128 pamoja na signal 9. Kivunji cha OOM cha kernel ndicho chanzo cha kawaida, lakini muda wa kusubiri wakati wa kuzima hutoa msimbo huo huo programu inapopuuza SIGTERM. Tumia docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' <container> ili kutofautisha hali hizo. true 137 ni kusitishwa kwa sababu ya kumbukumbu, na false 137 si hivyo.

Je, niweke mem_limit au deploy.resources.limits.memory?

Zote zinafanya kazi pamoja na docker compose. deploy.resources.limits.memory ndiyo muundo wa sasa wa Compose Specification na ndiyo chaguo bora kwa faili mpya. Weka mem_limit ikiwa sehemu nyingine ya faili yako tayari inatumia vifunguo vya zamani vya kiwango cha juu. Kuweka vyote viwili kwenye service moja hufanya faili iwe ngumu zaidi kusoma, kwa hiyo chagua kimoja na uthibitishe matokeo kwa docker inspect.

Kwa nini container yangu inatumia kikomo chake kamili cha kumbukumbu bila kusitishwa?

Thamani ya matumizi katika docker stats inajumuisha page cache, ambayo kernel huondoa kumbukumbu inapokabiliwa na shinikizo badala ya kuanzisha kusitishwa kwa OOM. Tumia docker compose exec <service> grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat na usome thamani ya anon, ambayo ni working set isiyoweza kurejeshwa. Thamani ya juu ya file pamoja na thamani ya chini ya anon inaonyesha container inayofanya uingizaji na utoaji wa diski, si container inayokaribia kusitishwa.

Ni RAM kiasi gani niachie bila kugawa kwenye VPS ya 8GB?

Acha takribani 1GB kwa ajili ya kernel, daemon ya Docker, sshd, journald na shell yako mwenyewe, kisha weka jumla ya vikomo vyote vya container chini ya 7GB iliyobaki. Fuatilia thamani ya juu ya anon kwa kila container chini ya mzigo halisi kwa siku moja kabla ya kuweka namba hizo, na ichukulie jumla hiyo kama bajeti, si lengo la kujaza.