SSD Nodes Learn Hosting plans →
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-31

Jinsi ya kuweka kikomo cha RAM kwenye Docker Compose

Zuia container moja kutumia RAM yote ya seva yako kwa kutumia deploy.resources. Jifunze kusanidi mem_limit ili kuepuka hitilafu ya exit 137 na kulinda VPS dhidi ya kuanguka.

Kikomo cha kumbukumbu katika Docker Compose hufanya nini

Kikomo cha kumbukumbu katika Docker Compose ni ukomo mkali ambao kernel ya Linux huweka kwenye cgroup ya container moja (control group, kipengele cha kernel kinachopima rasilimali kwa seti ya michakato). Weka deploy.resources.limits.memory kwenye huduma na container hiyo haitaweza kamwe kutumia zaidi ya namba uliyoiandika. Inapojaribu kufanya hivyo, kernel huua mchakato ndani ya container, na container hiyo kwa kawaida hutoka ikiwa na code 137.

Hili ni muhimu zaidi kwenye VPS, ambapo RAM imepangwa na hakuna kumbukumbu ya ziada ya host ya kukopa. Container moja yenye memory leak au query mbaya itachukua kila ukurasa wa kumbukumbu ulio wazi kwenye mashine ya 8GB. Kernel kisha huua mchakato wowote inaouona kuwa mbaya zaidi, ambao mara nyingi ni database au session yako ya SSH badala ya container iliyosababisha tatizo. Vikomo hubadilisha hitilafu ya seva nzima kuwa huduma moja inayojianzisha upya.

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

Tekeleza na uthibitishe kuwa kikomo kimeanza kufanya kazi:

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

Safu ya MEM USAGE / LIMIT inapaswa kusomeka kama 142MiB / 1GiB. Ikiwa safu ya kikomo inaonyesha RAM yote ya host, mpangilio haukutekelezwa, na sehemu iliyobaki ya mwongozo huu haitasaidia hadi hapo itakapofanya kazi. Ikiwa faili ya compose yenyewe ni ngeni kwako, misingi ya Docker Compose kwa VPS inaelezea muundo wa faili ambao mwongozo huu unajengia.

deploy.resources.limits au mem_limit: ni ipi inayotumika

Kuna tahajia mbili kwa wazo moja, na ndiyo sababu hii inachanganya.

mem_limit, mem_reservation, memswap_limit, cpus na cpu_shares ni funguo za kiwango cha juu za huduma (top-level service keys) zilizorithiwa kutoka kwenye miundo ya zamani ya faili za Compose. deploy.resources ilitoka kwenye schema ya Swarm na sasa ni sehemu ya Compose Specification, ambayo ndiyo muundo unaosomwa na docker compose leo.

Zote hufanya kazi kwenye seva moja. Compose V2, ambayo ni plugin ya docker compose, hutumia deploy.resources.limits na deploy.resources.reservations unapoendesha docker compose up, bila kuwa na Swarm cluster yoyote. Sehemu za block ya deploy zinazohusu Swarm pekee ni funguo nyingine: mode, placement, update_config na endpoint_mode zina maana kwa docker stack deploy na hupuuzwa na docker compose up. Kwa hivyo, ushauri wa kawaida kwamba "deploy inahitaji Swarm" si sahihi kwa sehemu ndogo ya resources, na kuufuata kutakuacha na huduma zisizo na kikomo chochote.

Chagua tahajia moja kwa kila mradi. Kuandika mem_limit: 512m na deploy.resources.limits.memory: 1g kwenye huduma moja kutafanya faili isiweze kusomeka kwa haraka. Badala ya kukisia ni namba ipi iliyoshinda, iulize daemon:

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

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

Nini hutokea wakati container inapofikia kikomo

Container haipunguzi kasi. Inakufa.

Wakati mchakato unaomba ukurasa wa kumbukumbu na cgroup imefikia memory.max yake, kernel kwanza hujaribu kurejesha nafasi inayoweza ndani ya cgroup hiyo: husafisha page cache, kisha kurudisha kurasa zinazoweza kuwekwa kwenye swap. Ikiwa urejeshaji huo hautoshi, OOM (out of memory) killer ya cgroup huchagua mchakato ndani ya container na kuutumia SIGKILL. Kuua PID 1 ya container husababisha container hiyo kufungwa. Exit code 137 ni 128 jumlisha signal 9, kwa hivyo 137 ni alama ya SIGKILL yoyote, si uthibitisho wa OOM pekee.

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

true 137 ni OOM kill. false 137 inamaanisha kitu kingine kimetuma SIGKILL, na sababu ya kawaida ni docker compose stop kufikia muda wake wa ziada wa sekunde kumi kwa sababu programu ilipuuza SIGTERM. Tofauti hiyo huokoa saa nyingi, kwa sababu matatizo hayo mawili hayana uhusiano wowote.

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

docker events --filter event=oom

Kisha soma log ya kernel, ambayo ndiyo rekodi inayobaki baada ya kuanzishwa upya (restart):

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

Uuaji wa cgroup huchapisha mstari unaoanza na Memory cgroup out of memory: Killed process 24713 (node). Mstari usio na kiambishi Memory cgroup ni OOM ya host, ambayo inamaanisha mashine yenyewe imekosa RAM. Hilo ndilo tatizo ambalo vikomo vinalenga kuzuia, kwa hivyo kuliona ni ishara kwamba jumla ya vikomo vyako ni kubwa mno, au huduma zingine hazina kikomo chochote.

Kwa restart: unless-stopped, mzunguko wa OOM hujificha vizuri, kwa sababu huduma huonekana iko juu katika docker compose ps sekunde moja baada ya kufa. Angalia safu ya uptime na idadi ya restart, na unganisha kikomo hicho na healthcheck inayoripoti programu kama isiyo na afya ili container inayokufa mara kwa mara ionekane bila wewe kuifuatilia.

Reservation ni kidokezo, limit ndiyo sheria

reservations.memory (au mem_reservation ya zamani) ni kiwango cha chini cha kuanzia. Docker inaielezea kama soft limit inayowashwa wakati daemon inapogundua msongamano au uhaba wa kumbukumbu kwenye host. Hii haizuii container kuvuka kiwango hicho, na haitoi hakikisho kwamba kumbukumbu itapatikana wakati container inaihitaji. Inaupa kernel upendeleo wa kurejesha kumbukumbu kutoka kwa container zilizovuka reservation zao kwanza.

Kwa hivyo, reservation haitoi ulinzi wowote yenyewe. Itumie kuashiria huduma unayotaka itendewe vyema wakati wa msongamano, na utegemee limit kwa ajili ya usalama. Weka reservation chini ya limit, vinginevyo container haitaanza: Docker itakataa usanidi huo kwa Minimum memory limit can not be less than memory reservation limit.

Uhasibu wa swap, kwa uwazi

Picha nyingi za VPS husafirishwa bila faili yoyote ya swap. Tekeleza swapon --show na free -h. Ikiwa jumla ya swap ni sifuri, kila mpangilio wa swap hapa chini haufanyi kazi, na kikomo chako cha kumbukumbu ni ukomo wa RAM pekee.

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 hizi mbili kuwa sawa kunafanya kontena isiwe na swap kabisa. Kuweka mem_limit na kuacha memswap_limit bila kuwekwa thamani 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, ambapo swap ni kaunta tofauti (memory.swap.max) na hii hufanya kazi bila usanidi wa ziada. Ujumbe wa zamani Your kernel does not support swap limit capabilities hutoka kwa seva za cgroup v1 zilizowashwa bila swapaccount=1. Kwenye mifumo hiyo, kikomo cha kumbukumbu bado hutumika wakati sehemu ya swap hupuuzwa.

Kuwa mkweli kuhusu kile ambacho swap inakupa. Inafanya OOM kill kuwa polepole, siyo kutokea kwa nadra, kwa sababu mchakato unaovuja kumbukumbu hujaza swap kwa furaha kama unavyojaza RAM. Wakati huo huo, kontena inayotumia swap kupita kiasi kwenye hifadhi ya pamoja ya VPS hupunguza kasi ya kila huduma nyingine kwenye seva. Kwa chochote kinachohitaji latency ndogo, kikomo sahihi bila swap hufeli haraka na kwa njia inayotabirika zaidi.

Kwa nini matumizi ya kumbukumbu huonekana mabaya kuliko hali halisi

Takwimu ya MEM USAGE katika docker stats inajumuisha page cache, kwa hivyo kontena linalosoma faili kubwa hupanda kuelekea kikomo chake na kubaki hapo. Hiyo ni hali ya kawaida, na si uvujaji wa kumbukumbu, kwa sababu cache safi hurejeshwa kabla ya OOM killer kuitwa. Huduma kama seva ya media ya Jellyfin inayojiendesha yenyewe itaonekana kuwa karibu na kikomo chake kila wakati kwa sababu hii hasa.

Gawanya namba hiyo katika cache na working set halisi 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 anonymous memory, working set ambayo haiwezi kufutwa. file ni page cache, ambayo inaweza kufutwa. Panga kikomo chako kulingana na anon pamoja na ziada, si kulingana na jumla. Faili ya memory.events hutatua mjadala huu moja kwa moja: kaunta ya oom_kill iliyo juu ya sifuri inamaanisha kernel imeua kitu ndani ya kontena hili tangu lilipoanza, na kaunta ya max inayopanda inamaanisha kontena linashikiliwa kwenye kikomo chake hivi sasa. Amri zote mbili zinahitaji shell na coreutils ndani ya image, kwa hivyo zinashindwa kufanya kazi kwenye distroless au scratch image.

Vikomo vya ukubwa kwenye VPS ya 8GB

Anza na seva pangishi (host), siyo programu zako. Kwenye VPS ya 8GB, acha takriban 1GB kwa ajili ya kernel, Docker daemon, sshd, journald na shell yako ya kuingia. Hii inakuachia takriban 7GB ya kugawanya, na jumla ya vikomo vya kila container inapaswa kubaki chini ya kiasi hicho. Overcommitting hufanya kazi hadi siku ambapo huduma mbili zinafikia kilele chake kwa wakati mmoja.

Mgawanyo unaofaa kwenye seva ya 8GB:

  • Reverse proxy: kikomo cha 128m. Hii ni process ndogo, na kikomo hiki kidogo hukamata mara moja usanidi wowote mbaya wakati wa reload.
  • PostgreSQL: kikomo cha 2g, huku shared_buffers ikiwa imewekwa kwenye takriban 512MB katika usanidi wa database.
  • Application container: kikomo cha 1g.
  • Background worker: kikomo cha 512m.
  • Media au file service: kikomo cha 2g, ambapo sehemu kubwa itakuwa page cache.

Usinakili namba hizo kwenye stack yako. Endesha huduma hizo chini ya mzigo halisi kwa siku moja, fuatilia docker stats, chukua thamani ya juu zaidi ya anon kwa kila container na uongeze takriban nusu yake kama nafasi ya ziada. Kikomo kilichowekwa kwa kubana sana ni kibaya zaidi kuliko kutokuwa na kikomo, kwa sababu huua huduma inayofanya kazi vizuri wakati wa ongezeko la kawaida la traffic.

Mtego mmoja unastahili tahadhari maalum. Kikomo hiki hakionekani kwa runtime nyingi isipokuwa kama utaziambia. PostgreSQL itapanga shared_buffers na work_mem kupita kikomo cha container yake na itauawa. JVM (Java virtual machine) inahitaji -XX:MaxRAMPercentage=75 ili kupanga heap yake kulingana na kikomo cha cgroup badala ya RAM ya seva pangishi. Node.js inahitaji --max-old-space-size katika megabytes, iwekwe chini ya kikomo cha container, vinginevyo garbage collector yake itaruhusu heap kukua hadi kernel iingilie kati. Ollama ni hadithi hiyo hiyo kwa kutumia kigezo tofauti, kwa sababu kuongeza num_ctx kunakuza KV cache kwa mamia ya megabytes na container hufa katikati ya prompt ndefu. Cgroup haijadiliani. Inaua.

Vikomo vya CPU hufanya kazi kwa njia tofauti kabisa

cpus: "1.5" inamaanisha asilimia 150 ya core moja, inayotekelezwa kama quota ya CFS (completely fair scheduler). Container hupata muda wa CPU wa 150ms katika kila kipindi cha 100ms, ikigawanywa katika threads zake zote. Inapotumia muda huo, kernel huilazimisha kusubiri kipindi kijacho.

Huo ndio utofauti muhimu. Container inayozidi kikomo chake cha kumbukumbu huawa (killed). Container inayozidi kikomo chake cha CPU hupunguziwa kasi (throttled) na kuendelea kufanya kazi, lakini kwa mwendo wa polepole. Kwa hivyo, ni salama kuweka kikomo cha CPU kwa ukali, wakati kikomo cha kumbukumbu kinahitaji nafasi ya ziada.

cpu_shares ni zana tofauti: ni uzito wa kulinganisha (relative weight) ambao hufanya kazi tu wakati CPU zimelemewa na kazi. Container mbili zenye shares za 1024 na 512 hugawana core yenye shughuli nyingi kwa uwiano wa takriban mbili kwa moja, na kwenye seva isiyo na shughuli, hakuna hata moja inayozuiwa. Tumia shares kupanga huduma kulingana na umuhimu wake, na utumie cpus unapohitaji kikomo cha kweli, kwa mfano kuzuia kazi ya transcode ya usiku isinyime rasilimali seva yako ya wavuti.

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 seva moja. Thibitisha hili kwa docker inspect --format '{{.HostConfig.Memory}}' <container>, ambayo huonyesha kikomo hicho kwa bytes na kuchapisha 0 wakati hakuna kikomo kilichowekwa. Funguo zilizo ndani ya deploy ambazo zinahitaji Swarm kikamilifu ni mode, placement, update_config na endpoint_mode.

Nambari ya kutoka 137 inamaanisha nini katika Docker Compose?

Inamaanisha mchakato mkuu umepokea SIGKILL, kwa sababu 137 ni 128 jumlisha signal 9. OOM killer ya kernel ndiyo sababu ya kawaida, lakini muda wa kuzima (shutdown timeout) hutoa nambari hiyo hiyo wakati programu inapuuza SIGTERM. Endesha docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' <container> ili kutofautisha sababu hizo. true 137 ni mauaji ya kumbukumbu (memory kill), na false 137 siyo.

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

Zote hufanya kazi na docker compose. deploy.resources.limits.memory ndiyo umbizo la sasa la Compose Specification na ndilo chaguo bora zaidi kwa faili mpya. Bakiza mem_limit ikiwa faili yako yote tayari inatumia funguo za zamani za ngazi ya juu. Kuweka zote mbili kwenye huduma moja hufanya faili kuwa ngumu kusomeka, kwa hivyo chagua moja na uthibitishe matokeo kwa docker inspect.

Kwa nini kontena langu linakaa kwenye kikomo chake cha juu cha kumbukumbu bila kuuawa?

Takwimu ya matumizi katika docker stats inajumuisha page cache, ambayo kernel huiondoa wakati wa shinikizo badala ya kusababisha OOM kill. Endesha 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 kando ya thamani ya chini ya anon inamaanisha kontena linafanya shughuli za kusoma na kuandika kwenye diski, si kontena linalokaribia kufa.

Ni kiasi gani cha RAM ninapaswa kuacha bila kutengwa kwenye VPS ya 8GB?

Acha takriban 1GB kwa ajili ya kernel, Docker daemon, sshd, journald na shell yako, kisha weka jumla ya vikomo vyote vya kontena chini ya 7GB iliyobaki. Fuatilia thamani ya juu ya anon kwa kila kontena chini ya mzigo halisi kwa siku moja kabla ya kuamua nambari, na chukulia jumla hiyo kama bajeti badala ya lengo la kujaza.