Varsayılan olarak bir container, host’un bellek ve CPU’sunun tamamını kullanabilir. Bu, tek bir kontrolden çıkmış container’ın (bellek sızıntısı, sonsuz döngü, fork bombası) aynı makinedeki tüm diğer servisleri çökertebileceği anlamına gelir. Kaynak limitleri, bir container’ın ne kadar kullanabileceğini sınırlayarak hasarı kendi içinde tutar. Bu yazıda bellek, CPU ve süreç sayısı limitlerini, aşıldıklarında ne olduğunu gerçek çıktılarla gösteriyoruz.

Temel bayraklar

Bayrak Ne yapar?
--memory / -m Sert bellek sınırı (en az 6 MB). Aşılırsa süreç öldürülür
--memory-swap Bellek + swap toplamı. --memory ile aynı değer = swap kullanımı yok
--memory-reservation Yumuşak sınır; yalnızca host’ta bellek sıkışıklığı olduğunda devreye girer, garanti vermez
--cpus Kullanılabilecek CPU miktarı (örn. 0.5 = yarım çekirdek)
--cpu-shares CPU sıkışıklığında göreli ağırlık (sert sınır değil)
--cpuset-cpus Container’ı belirli çekirdeklere sabitler
--pids-limit Container içinde en fazla kaç süreç olabileceği

Limit koyup doğrulamak

docker run -d --name lim \
  --memory=64m --memory-swap=64m --memory-reservation=32m \
  --cpus=0.5 --pids-limit=20 \
  imaj sleep 120

$ docker inspect lim --format 'Memory={{.HostConfig.Memory}} Swap={{.HostConfig.MemorySwap}} NanoCpus={{.HostConfig.NanoCpus}} Pids={{.HostConfig.PidsLimit}}'
Memory=67108864 Swap=67108864 NanoCpus=500000000 Pids=20

$ docker stats --no-stream lim
lim  mem=656KiB / 64MiB  cpu=0.00%  pids=1

docker stats çıktısındaki / 64MiB, limitin gerçekten uygulandığını gösterir. Limitlerin çekirdekte nasıl göründüğüne bakmak isterseniz, container içindeki cgroup dosyaları değerleri doğrular. Denediğimiz ortamda (cgroup v1) memory.limit_in_bytes 67108864 ve pids.max 20 okundu. Modern Linux dağıtımlarının çoğunda kullanılan cgroup v2’de aynı bilgi /sys/fs/cgroup/memory.max ve pids.max dosyalarındadır.

i

Bu denemeyi yaptığımız Docker 29.4 ortamı cgroup v1 üzerindeydi ve Docker “cgroup v1 desteği kullanımdan kaldırılmıştır, en geç Mayıs 2029’a kadar kaldırılacaktır” uyarısı verdi. Yeni kurulumlarda cgroup v2 beklemelisiniz.

Bellek limiti aşılınca: OOM

Container belleği sert sınırını aşarsa çekirdeğin OOM (out-of-memory) mekanizması süreci öldürür. Bunu 16 MB sınırı olan bir container’da ~40 MB’lık bir değişken oluşturarak tetikledik:

$ docker run --name oom --memory=16m --memory-swap=16m imaj sh -c 'x=$(head -c 40000000 /dev/zero | tr "\0" "a"); echo ${#x}'
$ echo $?
137

$ docker inspect oom --format 'OOMKilled={{.State.OOMKilled}} ExitCode={{.State.ExitCode}}'
OOMKilled=true ExitCode=137

Çıkış kodu 137 (128 + SIGKILL 9) ve OOMKilled=true — bir container’ın “sebepsiz” sürekli yeniden başladığını görürseniz ilk bakacağınız yer budur. Uygulamanın gerçek bellek ihtiyacını ölçün (docker stats) ve limiti buna göre, biraz pay bırakarak ayarlayın; çok düşük limit servis kesintisi, çok yüksek limit koruma kaybı demektir.

Süreç limiti: fork bombasına karşı

--pids-limit, bir container’ın sınırsız süreç üretmesini engeller. Limit 5 iken sekiz arka plan süreci başlatmayı denediğimizde kabuk şunu söyledi:

$ docker run --rm --pids-limit=5 imaj sh -c 'for i in 1 2 3 4 5 6 7 8; do sleep 5 & done'
/bin/sh: 0: Cannot fork

Limit aşılınca yeni süreç oluşturulamıyor; böylece bir fork bombası host’u değil yalnızca kendi container’ını tıkar.

Compose’ta limitler

services:
  api:
    image: uygulama:1
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 256M
        reservations:
          memory: 128M
    pids_limit: 200

Bu tanımlar Compose’un deploy.resources bölümündeki limit ve rezervasyonlara karşılık gelir. Docker Swarm ve Kubernetes’te de benzer kavramlar vardır (Kubernetes’te resources.requests/limits), bkz. Kubernetes Temelleri.

Pratik öneriler

  • Her üretim container’ına bellek limiti koyun. En azından --memory; “limitsiz” bir container komşularını tehlikeye atar.
  • --memory-swap‘ı --memory ile eşitleyin (swap kapalı): yavaş, öngörülemez swap davranışı yerine hızlı ve net bir OOM tercih edilir.
  • --oom-kill-disable‘dan kaçının. Yalnızca --memory ile birlikte kullanılmalıdır; aksi halde host kararsızlaşabilir.
  • --pids-limit ekleyin (örn. 100–500, uygulamaya göre).
  • İzleyin. Limitlere ne kadar yaklaştığınızı görmek için izleme ve loglama kurun; OOM olaylarını alarma bağlayın.

Hızlı kontrol listesi

  • Her servisin bellek ve CPU limiti tanımlı mı?
  • Swap devre dışı mı (memory-swap = memory)?
  • docker inspect ile OOMKilled geçmişi kontrol ediliyor mu?
  • pids-limit tanımlı mı?

Güvenlik açısından kaynak limitleri, container izolasyonunun bir parçasıdır; daha geniş çerçeve için sitemizdeki Güvenlik Merkezi aracına bakın.