Girişimsel kardiyolojide kalp damar tıkanıklıklarını açmak için en modern yöntemlerden biri, damar içine ilaç salınımlı titanyum-kobalt alaşımlı koroner stent yerleştirmektir. Bu stent, çökmüş bir koroner arteri saniyeler içinde açar ve kalbe hayat verir. Ancak cerrah bu stenti takıp hastayı eve gönderirken antiagregan (kan sulandırıcı) reçetesi yazmazsa veya hastanın pıhtılaşma takibini yapmazsa ne olur? Stentin metal kafesi etrafında kontrolsüzce endotelyal hücreler, fibröz dokular ve mikroskobik trombositler birikmeye başlar. Aylar içinde o hayat kurtaran stent, damarın içinde devasa bir trombüs kütlesine (stent trombozu) dönüşür; damarı tamamen tıkar ve hasta masif bir miyokard enfarktüsüyle (kalp krizi) acile döner. En son teknoloji donanım, basit bir temizlik ve takip protokolü uygulanmadığı için hastanın ölüm sebebi olmuştur.

Modern yazılım mühendisliğinde ve DevOps dünyasında Docker konteynır teknolojisine geçiş tam olarak bu stent takma ameliyatıdır. Monolitik, hantal uygulamaları izole, taşınabilir ve şık konteynırlara koyarsınız. Ancak Docker motorunun varsayılan günlük kaydı sürücüsü olan json-file için bir boyut sınırı (log rotation) tanımlamazsanız; o modern konteynır aylar içinde yüzlerce gigabaytlık bir log canavarına dönüşür ve sunucunun tüm diskini yutarak sistemi felç eder.


Docker'ın Varsayılan Tuzağı: Sınırsız json-file Sürücüsü

Birçok geliştirici Docker'ı kurar, docker run veya docker compose up -d komutunu verir ve uygulamanın arka planda izole bir şekilde çalıştığını görerek rahatlar.

Konteynır içinde çalışan uygulamanın (Node.js, Go, Python, Java) konsola bastığı her çıktı (stdout ve stderr), Docker daemon tarafından yakalanır.

Docker'ın varsayılan günlük kaydı mimarisi şu şekildedir:

  • Varsayılan sürücü: json-file
  • Varsayılan dosya konumu: /var/lib/docker/containers/<container-id>/<container-id>-json.log
  • Varsayılan dosya boyutu sınırı: SINIRSIZ (UNLIMITED)!
  • Varsayılan dosya adedi: 1 (ROTASYON YOK!)
[Konteynır Uygulaması]
  │ console.log("Kullanıcı bağlandı: 192.168.1.1")
  ▼
[Docker Daemon]
  │ JSON Formatına Çevir: {"log":"Kullanıcı bağlandı...","stream":"stdout","time":"..."}
  ▼
[/var/lib/docker/containers/...-json.log]
  │
  ├─ Gün 1   : 20 MB
  ├─ Ay 1    : 14 GB
  ├─ Ay 6    : 112 GB! (Disk Alanı: %100 - TÜM DOCKER MOTORU KİLİTLENDİ!)

Docker daemon, siz açıkça "dur" demediğiniz sürece o dosyayı sonsuza kadar büyütür. Tek bir satır log bile silinmez.


Patolojinin Gelişimi: "Disk Nereye Kayboldu?"

Pazartesi sabahı sunucu izleme araçlarından (Zabbix, Grafana) kırmızı alarmlar düşer: Sunucuda 160 GB NVMe disk vardır ve kullanılabilir alan 0 MB kalmıştır.

Sistem yöneticisi SSH ile sunucuya bağlanır ve du -sh /* komutuyla diski neyin yediğini aramaya başlar:

  • /var/www -> 4 GB
  • /var/log -> 800 MB (Çünkü sistem logrotate çalışıyor)
  • /home -> 1 GB
  • /var/lib/docker -> 148 GB!

Yönetici docker system df yazar:

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          12        4         4.2GB     2.8GB (66%)
Containers      4         4         320MB     0B (0%)
Local Volumes   3         3         1.8GB     0B (0%)
Build Cache     0         0         0B        0B

Yönetici şaşkına döner: "İmajlar 4 GB, konteynırlar 300 MB, volumeler 2 GB. 140 GB nerede?!"

docker system df komutu konteynırların log dosyası boyutlarını varsayılan olarak göstermez! O 140 GB, Docker'ın iç organlarında gizlenen <id>-json.log dosyasının ta kendisidir!

# Gerçek katili ortaya çıkaran komut:
ls -lh /var/lib/docker/containers/*/*-json.log
 
# ÇIKTI DEHŞET VERİCİDİR:
# -rw-r----- 1 root root 138G Oca 17 04:12 8f9a2b1c4d...-json.log

Acil Müdahale: Canlı Konteynırın Logunu Boşaltmak

Acemi mühendisin ilk refleksi rm -f /var/lib/docker/containers/*/*.log yapmaktır. Bir önceki makalemizde anlattığımız gibi; Docker daemon o dosyayı açık bir dosya tanıtıcısıyla (file descriptor) tuttuğu için dosya silinmez, "hayalet dosya" olarak bellekte asılı kalır ve disk alanı açılmaz!

Konteynırı durdurmadan (downtime yaratmadan) o 140 GB'lık kütüğü anında sıfırlamanın tek yolu truncate uygulamaktır:

# Canlıdaki tüm Docker log dosyalarını güvenle sıfırlar:
truncate -s 0 /var/lib/docker/containers/*/*-json.log

Komut bittiği saniye df -h çıktısında 140 GB alanın anında açıldığını görürsünüz. Hasta tekrar nefes almaya başlamıştır. Ancak bu geçici bir pansumandır; damara stent takılmış ama hala kan sulandırıcı verilmemiştir.


Radikal Tedavi: Docker Seviyesinde Global Log Rotasyonu

Konteynırların bir daha asla diski yutmaması için kalıcı ve sistemsel bir sınır getirilmelidir. Bunu her konteynıra tek tek yapmak yerine doğrudan Docker motorunun kalbine işlemek gerekir.

1. Global Çözüm: /etc/docker/daemon.json

Docker daemon yapılandırma dosyası açılır (yoksa oluşturulur):

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3"
  }
}

Bu iki parametrenin anlamı hayati önemdedir:

  • max-size: "50m": Tek bir log dosyasının boyutu 50 Megabayt'ı geçtiğinde dosya derhal kapatılır ve döndürülür.
  • max-file: "3": En fazla 3 adet arşiv dosyası tutulur. Dördüncü dosya oluştuğunda en eski dosya otomatik olarak imha edilir.

Bu kuralı girdikten sonra Docker servisi yeniden yüklenir:

sudo systemctl reload docker

Artık bu sunucuda ayağa kalkan hiçbir konteynır toplamda 50 MB x 3 = 150 MB'tan fazla log üretemez! 150 MB'a ulaşan log kendi kendini imha eden döngüsel bir hafızaya (ring buffer) dönüşür.


2. Docker Compose Seviyesinde Sınırlandırma

Eğer global ayar yapamıyorsanız veya belirli bir mikroservisin (örneğin aşırı debug logu basan bir kuyruk dinleyicisinin) logunu daha da sıkı tutmak istiyorsanız, bunu doğrudan docker-compose.yml içinde tanımlayabilirsiniz:

version: '3.8'
 
services:
  backend-api:
    image: my-app:latest
    restart: always
    logging:
      driver: "json-file"
      options:
        max-size: "20m"
        max-file: "2"
    ports:
      - "3000:3000"

Bu servis için toplam log tavanı 40 MB ile kesin olarak sınırlandırılmıştır.


Kurumsal Mimari: Logları Konteynırdan Dışarı Fırlatmak

Logların konteynır içinde veya sunucunun yerel diskinde saklanması, 12-Factor App (On İki Faktörlü Uygulama) prensiplerine de aykırıdır. Bir konteynır geçicidir (ephemeral); gerektiğinde ölür, yeniden doğar.

Kurumsal altyapılarda Docker log sürücüsü yerel disk yerine doğrudan merkezi bir log toplayıcıya yönlendirilir:

  • Loki Sürücüsü (loki): Grafana Loki'ye doğrudan HTTP ile log akışı sağlar.
  • Fluentd / Logstash (fluentd): Logları toplayıp Elasticsearch / OpenSearch kümesine fırlatır.
  • Syslog Sürücüsü (syslog): İşletim sisteminin merkezi rsyslog servisine aktarır.

Bu mimaride konteynır sunucusunun diskinde tek bir bayt bile log birikmez; loglar anında merkezi SIEM havuzuna akar ve disk dolma riski teorik olarak sıfıra iner.

Sonuç

Stent takmak cerrahiyi bitirmez; stentin tıkanmasını önleyecek tedaviyi düzenlemek zorundasınız. Docker kullanmak da sistem yönetimini bitirmez; konteynırın ürettiği atığın sunucuyu boğmasını engelleyecek limitleri koymak zorundasınız.

Sınırlandırılmamış her süreç, kaynakları sonsuz zanneden bir parazite dönüşür. Docker projelerinize başlarken max-size parametresini bir opsiyon değil, altyapınızın yaşamsal emniyet kemeri olarak kabul edin.