← Kursa Dön
📄 Text · 30 min

Troubleshooting — Debug Teknikleri ve Yaygın Sorunlar

Monitoring ve logging'i kurduk, harika. Ama bir gün alarm çalacak — bir container çökecek, bir servis yanıt vermeyecek, disk dolacak. O an ne yapacaksın? Panik mi yapacaksın, yoksa sistematik bir şekilde sorunu tespit edip çözecek misin? Bu ders, Docker'da karşılaşabileceğin sorunları sistematik olarak çözmeyi öğretiyor. Bir nevi "Docker acil durum el kitabı."

Bir dedektif gibi düşün. Olay yerine geliyorsun — bir şeyler yanlış gitmiş. İlk iş: kanıtları topla (loglar). Sonra tanıkları dinle (metrikler). Kronolojik sırayla olayları yeniden oluştur (event'ler). Şüphelileri daralt (root cause analysis). Ve çözümü uygula.

Docker troubleshooting da aynı süreç. Container çöktü? Neden çöktü? Log'lara bak, exit code'u incele, kaynak kullanımını kontrol et, network bağlantısını test et. Bu ders, Docker'da karşılaşacağın sorunların sistematik çözüm yollarını öğretiyor — paniğe gerek yok, prosedürü izle.

Troubleshooting Metodolojisi

Her sorun için bu sırayı takip et:

1. GÖZLE    → docker ps -a, docker stats, docker events
2. OKU      → docker logs, docker inspect
3. TEST ET  → docker exec, network check, disk check
4. DARALT   → Hangi katmanda sorun? (app, container, host, network)
5. ÇÖZMLE   → Fix uygula, doğrula, dokümante et

Docker Katmanları

┌─────────────────────────────────────┐
│  Uygulama Katmanı                   │  → Kod hatası, konfigürasyon
├─────────────────────────────────────┤
│  Container Katmanı                   │  → Resource limit, restart, OOM
├─────────────────────────────────────┤
│  Docker Engine Katmanı              │  → Daemon sorunları, storage driver
├─────────────────────────────────────┤
│  Network Katmanı                    │  → DNS, port, connectivity
├─────────────────────────────────────┤
│  Host Katmanı                       │  → Disk, CPU, memory, kernel
└─────────────────────────────────────┘

Temel Debug Komutları

Container Durumu

# Tüm container'lar (çalışan + durmuş)
docker ps -a
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}\t{{.Size}}"

# Sadece sorunlular
docker ps -a --filter "status=exited"
docker ps -a --filter "status=restarting"
docker ps -a --filter "status=dead"

# Son 10 dakikada oluşturulan
docker ps -a --filter "since=10m"

Container Logları

# Son loglar
docker logs myapp
docker logs --tail 100 myapp          # Son 100 satır
docker logs --since 30m myapp         # Son 30 dakika
docker logs --since 2024-01-15T10:00:00 myapp  # Belirli zamandan

# Canlı log takibi
docker logs -f myapp
docker logs -f --tail 0 myapp         # Sadece yeni loglar

# Tüm compose servislerinin logları
docker compose logs -f
docker compose logs -f api db         # Belirli servisler

# Log'u dosyaya yaz
docker logs myapp > /tmp/myapp.log 2>&1

Container İnceleme

# Detaylı bilgi
docker inspect myapp

# Belirli alanlar
docker inspect myapp --format '{{.State.Status}}'        # Status
docker inspect myapp --format '{{.State.ExitCode}}'      # Exit code
docker inspect myapp --format '{{.State.OOMKilled}}'     # OOM mi?
docker inspect myapp --format '{{.State.Error}}'         # Hata mesajı
docker inspect myapp --format '{{.State.StartedAt}}'     # Ne zaman başladı
docker inspect myapp --format '{{.State.FinishedAt}}'    # Ne zaman durdu
docker inspect myapp --format '{{.RestartCount}}'        # Restart sayısı
docker inspect myapp --format '{{json .NetworkSettings.Networks}}' | jq  # Network detay

# Kaynak limitleri
docker inspect myapp --format '{{.HostConfig.Memory}}'   # Memory limit
docker inspect myapp --format '{{.HostConfig.NanoCpus}}'  # CPU limit

Gerçek Zamanlı Metrikler

# Tüm container'ların kaynak kullanımı
docker stats
docker stats --no-stream                   # Anlık snapshot
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"

# Belirli container
docker stats myapp

# Compose servislerinin kaynak kullanımı
docker compose stats

Event'ler (Olay Geçmişi)

# Son olaylar
docker events --since 1h
docker events --since 1h --filter type=container
docker events --since 1h --filter event=die
docker events --since 1h --filter event=oom

# Belirli container'ın olayları
docker events --filter container=myapp --since 30m

# JSON formatında (parse için)
docker events --format '{{json .}}' --since 1h

Sorun 1: Container Başlamıyor

Exit Code Analizi

docker inspect myapp --format '{{.State.ExitCode}}'
Exit CodeAnlamıYaygın SebepÇözüm
0Normal çıkışCMD tamamlandıCMD'nin sürekli çalışan bir process olduğundan emin ol
1Uygulama hatasıKod hatası, eksik configLog'lara bak, env değişkenlerini kontrol et
126Permission deniedÇalıştırılabilir değilchmod +x veya doğru user
127Command not foundYanlış CMD/ENTRYPOINTDockerfile'ı kontrol et
137SIGKILL (OOM)Bellek limiti aşıldıMemory limit artır
139SIGSEGVSegmentation faultUygulama bug'ı, native lib sorunu
143SIGTERMGraceful shutdownNormal — dışarıdan durduruldu

OOM Killed Analizi

# Container OOM killed mi?
docker inspect myapp --format '{{.State.OOMKilled}}'
# true → Bellek limiti yetersiz

# Host'ta OOM olayları
dmesg | grep -i "oom\|out of memory" | tail -20
journalctl -k | grep -i oom

# Çözüm:
# 1. Memory limiti artır
docker update --memory=1g --memory-swap=2g myapp

# 2. Uygulama memory leak'ini düzelt
# 3. Memory profiling yap

Container Hemen Çıkıyor (Exit 0)

# Sebep: CMD foreground'da çalışmıyor

# ❌ Background'da çalışır ve container çıkar
CMD service nginx start

# ✅ Foreground'da çalışır
CMD ["nginx", "-g", "daemon off;"]

# ❌ Shell script background'da
CMD ./start.sh &

# ✅ Shell script foreground'da
CMD ["./start.sh"]
# start.sh'ın sonunda exec ile ana process'i başlat:
# exec java -jar app.jar

Container "Restarting" Döngüsünde

# Restart sayısını kontrol et
docker inspect myapp --format '{{.RestartCount}}'

# Son birkaç restart'ın loglarını gör
docker logs --tail 50 myapp

# Restart policy'yi geçici olarak kaldır (debug için)
docker update --restart=no myapp

# Container'ı manuel başlat ve debug et
docker run -it --entrypoint sh myapp:latest
# İçeride CMD'yi elle çalıştır ve hatayı gör

Sorun 2: Container Yavaş Çalışıyor

CPU Analizi

# CPU kullanımını izle
docker stats --format "table {{.Name}}\t{{.CPUPerc}}" myapp

# Container içinde process'leri gör
docker exec myapp top -bn1
docker exec myapp ps aux --sort=-%cpu | head -10

# CPU throttling kontrol
cat /sys/fs/cgroup/cpu/docker/CONTAINER_ID/cpu.stat
# nr_throttled > 0 ise CPU limit'e takılıyor

# Çözüm: CPU limit artır
docker update --cpus=2 myapp

Memory Analizi

# Memory kullanımı
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}" myapp

# Container içinde memory detayı
docker exec myapp cat /proc/meminfo | head -5
docker exec myapp free -h

# Hangi process en çok memory kullanıyor?
docker exec myapp ps aux --sort=-%mem | head -10

# Memory leak tespiti — zamanla artıyor mu?
watch -n 5 'docker stats --no-stream --format "{{.MemUsage}}" myapp'

Disk I/O Analizi

# Container disk kullanımı
docker system df -v | grep myapp

# Container içinde disk durumu
docker exec myapp df -h
docker exec myapp du -sh /app/*

# Block I/O
docker stats --no-stream --format "table {{.Name}}\t{{.BlockIO}}" myapp

# I/O yoğun process'ler
docker exec myapp iotop -bn1 2>/dev/null || echo "iotop not installed"

Sorun 3: Network Sorunları

DNS Çözümleme

# Container içinden DNS testi
docker exec myapp nslookup db
docker exec myapp getent hosts db

# DNS çözümlemesi başarısız olursa:
# 1. Aynı network'te mi kontrol et
docker network inspect mynetwork | jq '.[0].Containers'

# 2. Docker DNS servisini kontrol et
docker exec myapp cat /etc/resolv.conf
# nameserver 127.0.0.11 olmalı (Docker internal DNS)

Port ve Bağlantı Testi

# Container'dan başka servise bağlantı
docker exec myapp wget -qO- --timeout=5 http://api:3000/health
docker exec myapp nc -zv db 5432
docker exec myapp curl -s http://redis:6379/ping

# Host'tan container'a bağlantı
curl http://localhost:8080/health
nc -zv localhost 8080

# Port mapping doğru mu?
docker port myapp
# 3000/tcp -> 0.0.0.0:8080

# Container IP'si
docker inspect myapp --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'

Network Debug — Netshoot

# Netshoot — tüm network debug araçlarını içeren container
docker run -it --rm \
    --net container:myapp \
    nicolaka/netshoot

# İçeride:
# ping db
# dig db
# curl http://api:3000/health
# tcpdump -i eth0 port 5432
# ss -tlnp
# iftop
# mtr db
# nmap -p 5432 db

Container'lar Arası İletişim Problemi

# 1. Aynı network'te mi?
docker inspect myapp --format '{{json .NetworkSettings.Networks}}' | jq
docker inspect db --format '{{json .NetworkSettings.Networks}}' | jq

# 2. Network doğru mu?
docker network ls
docker network inspect bridge

# 3. Container ismi doğru mu?
# Docker Compose: service adı = DNS adı
# docker run: --name ile verilen ad = DNS adı (aynı network'te)

# 4. Port doğru mu?
# EXPOSE sadece dökümantasyon — gerçek erişim container port'u ile
docker exec myapp wget -qO- http://db:5432  # ✅ Container port
# http://db:15432 değil ← Bu host port mapping'i

Sorun 4: Disk ve Storage Sorunları

Docker Disk Kullanımı

# Genel durum
docker system df
# TYPE            TOTAL   ACTIVE   SIZE      RECLAIMABLE
# Images          25      5        8.5GB     6.2GB (72%)
# Containers      8       3        250MB     200MB (80%)
# Local Volumes   12      4        3.2GB     1.8GB (56%)
# Build Cache     50      0        2.1GB     2.1GB (100%)

# Detaylı
docker system df -v

# En büyük image'lar
docker images --format "{{.Size}}\t{{.Repository}}:{{.Tag}}" | sort -rh | head -10

# En büyük container'lar
docker ps -as --format "table {{.Names}}\t{{.Size}}"

Temizlik Prosedürleri

# === Güvenli Temizlik ===
# Durmuş container'ları sil
docker container prune -f

# Kullanılmayan image'ları sil (dangling)
docker image prune -f

# Build cache temizle
docker builder prune -f

# === Orta Agresif Temizlik ===
# 7 günden eski kullanılmayan image'ları sil
docker image prune -a --filter "until=168h" -f

# === Agresif Temizlik (⚠️ DİKKATLİ) ===
# Her şeyi temizle (kullanılmayan container, image, network, volume)
docker system prune -a --volumes -f
# ⚠️ Volume'lar silinir — veri kaybı riski!

Log Dosyaları Şişmiş

# Büyük log dosyalarını bul
find /var/lib/docker/containers -name "*.log" -size +100M -exec ls -lh {} \;

# Acil: Log dosyasını truncate et (container çalışırken)
truncate -s 0 /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log

# Kalıcı çözüm: Log rotasyonu ayarla
# /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
# Ardından: sudo systemctl restart docker

"No space left on device" Hatası

# 1. Host disk durumu
df -h

# 2. Docker'ın kullandığı alanı kontrol et
du -sh /var/lib/docker/

# 3. Temizle
docker system prune -a -f

# 4. Overlay2 storage driver temizliği
# ⚠️ Dikkatli: sadece gerçekten gerekiyorsa
du -sh /var/lib/docker/overlay2/* | sort -rh | head -10

# 5. Root partition doluysa acil çözüm
# Kullanılmayan kernel'ları sil (Ubuntu)
sudo apt autoremove --purge

Sorun 5: Image Build Sorunları

Build Hata Ayıklama

# Verbose build output
docker build --progress=plain -t myapp .

# Build'i belirli stage'de durdur
docker build --target builder -t myapp:debug .
docker run -it myapp:debug sh
# İçeride dosyaları, paketleri kontrol et

# Build context çok büyük
du -sh .
# .dockerignore'u kontrol et — node_modules, .git dahil mi?

# Build cache durumu
docker builder du
# Çok büyükse:
docker builder prune -f

Dockerfile Debugging

# Debug: Her RUN komutundan sonra dosyaları kontrol et
FROM node:20-alpine AS debug
WORKDIR /app
COPY package*.json ./
RUN npm ci && ls -la node_modules/ | head -20
COPY . .
RUN ls -la && echo "=== Build output ===" && npm run build && ls -la dist/
# Intermediate layer'a girip incele
# BuildKit kapalıyken (legacy builder):
DOCKER_BUILDKIT=0 docker build -t myapp .
# Her step bir layer oluşturur — docker run <layer-id> sh ile girip inceleyebilirsin

Sorun 6: Docker Compose Sorunları

Service Başlamıyor

# Compose logları
docker compose logs
docker compose logs api --tail 50

# Belirli service'i debug et
docker compose up api    # Foreground'da başlat — çıktıyı gör

# depends_on sorunu — bağımlı servis hazır değil
# healthcheck ekle:
services:
  db:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      retries: 10
  api:
    depends_on:
      db:
        condition: service_healthy

Environment Variable Sorunu

# ENV değişkenlerini kontrol et
docker compose config    # Tüm interpolasyonu gösterir

# Container içindeki ENV'leri kontrol et
docker compose exec api env | sort

# .env dosyası yükleniyor mu?
cat .env
docker compose --env-file .env config

Volume Permission Sorunu

# Bind mount permission hatası
# Sebep: Container'daki user ile host'taki dosya ownership uyuşmuyor

# Container içinde user ID'yi kontrol et
docker compose exec api id
# uid=1000(app) gid=1000(app)

# Host'ta dosya ownership'i kontrol et
ls -la ./data/

# Çözüm 1: Dockerfile'da user ID'yi ayarla
RUN addgroup -g 1000 app && adduser -u 1000 -G app -D app

# Çözüm 2: Host'ta ownership değiştir
sudo chown -R 1000:1000 ./data/

Sorun 7: Docker Daemon Sorunları

# Daemon durumu
sudo systemctl status docker
docker info

# Daemon logları
sudo journalctl -xu docker.service --since "1 hour ago"
sudo journalctl -xu docker.service -f    # Canlı

# Daemon yanıt vermiyor
sudo systemctl restart docker

# Docker socket erişim hatası
ls -la /var/run/docker.sock
# Kullanıcı docker grubunda mı?
groups $USER
sudo usermod -aG docker $USER
# Oturumu yeniden aç

Debug Container — Sidecar Yaklaşımı

Crashlanan veya minimal image'a (distroless) sahip container'ları debug etmek için:

Kubernetes Debug Container

# Kubernetes ephemeral debug container
kubectl debug -it myapp-pod --image=nicolaka/netshoot --target=myapp
# myapp container'ının PID namespace'ine erişir

# Veya ayrı bir debug pod
kubectl run debug --rm -it --image=nicolaka/netshoot -- bash

Docker Debug Teknikleri

# 1. Override entrypoint — crash eden container'a gir
docker run -it --entrypoint sh myapp:latest
# İçeride CMD'yi elle çalıştır, hatayı gör

# 2. Sidecar debug container — aynı network + pid namespace
docker run -it --rm \
    --pid=container:myapp \
    --net=container:myapp \
    nicolaka/netshoot

# İçeride:
# ps aux (myapp'ın process'lerini görürsün)
# ss -tlnp (myapp'ın portlarını görürsün)
# strace -p 1 (myapp'ın syscall'larını izle)

# 3. Çökmüş container'ın dosyalarını al
docker cp myapp:/app/logs/error.log ./error.log
docker cp myapp:/etc/nginx/nginx.conf ./nginx.conf

# 4. Container'ın filesystem'ini image olarak kaydet
docker commit myapp debug-snapshot:$(date +%Y%m%d)
docker run -it debug-snapshot:20240115 sh

Emergency Playbook — Acil Durum Prosedürleri

Senaryo 1: Tüm Container'lar Çöktü

# 1. Docker daemon çalışıyor mu?
sudo systemctl status docker

# 2. Disk dolu mu?
df -h
docker system df

# 3. OOM killer çalıştı mı?
dmesg | grep -i oom | tail -10

# 4. Docker event'leri
docker events --since 1h

# 5. Daemon restart
sudo systemctl restart docker

# 6. Container'ları tekrar başlat
docker compose up -d

Senaryo 2: Yavaş/Yanıt Vermeyen Container

# 1. Kaynak kullanımını kontrol et
docker stats myapp --no-stream

# 2. Container içi kontrol
docker exec myapp top -bn1
docker exec myapp ss -tlnp | wc -l    # Bağlantı sayısı

# 3. Goroutine/thread dump (dile göre)
# Java: docker exec myapp jstack 1
# Go: docker exec myapp curl localhost:6060/debug/pprof/goroutine?debug=2
# Node: docker exec myapp kill -USR1 1  (heap dump)

# 4. Gerekirse restart
docker restart myapp

Senaryo 3: Database Container Veri Kaybı

# 1. Volume kontrol
docker volume inspect pgdata
docker volume ls

# 2. Container'ı durdur (panik yapma, silme!)
docker stop db

# 3. Volume'daki veriyi kontrol et
docker run --rm -v pgdata:/data alpine ls -la /data/

# 4. Backup'tan restore
docker run --rm -v pgdata:/data -v /backup:/backup alpine \
    sh -c "rm -rf /data/* && tar xzf /backup/pgdata-latest.tar.gz -C /data/"

# 5. Database'i tekrar başlat
docker start db

Best Practices

Yap:

  • Exit code analizi ile başla — çoğu sorunu exit code açıklar

  • Structured logging kullan — log'ları parse etmek kolaylaşır

  • Health check her container'a ekle — sorunları erken yakala

  • docker events izle — container lifecycle olaylarını takip et

  • netshoot container'ını hazır tut — network debug için mükemmel

  • Sorun çözümlerini runbook olarak dokümante et — tekrar yaşanırsa hızlı çöz

  • Monitoring kur — sorunları oluşmadan önce yakala

  • Düzenli backup al ve restore testi yap

Yapma:

  • Container çöktüğünde hemen silme — önce log'ları al, inspect et

  • Sorunlu container'ı docker exec ile düzeltme — yeni image build et

  • Production'da -f (force) flag'ini düşünmeden kullanma

  • docker system prune --volumes komutunu production'da alışkanlık yapma

  • Log rotasyonu olmadan container çalıştırma — disk dolar

  • Debug bilgilerini production'da açık bırakma (verbose logging, debug port)

Özet

  • Sistematik yaklaşım: Gözle → Oku → Test et → Daralt → Çöz

  • Exit code en önemli ipucu: 137=OOM, 1=uygulama hatası, 127=komut bulunamadı

  • docker logs, inspect, stats, events — dört temel debug komutu

  • Network debug: DNS kontrolü, port testi, netshoot sidecar container

  • Disk sorunları: docker system df, temizlik prosedürleri, log rotasyonu

  • Build debug: --progress=plain, stage'de durdurma, intermediate layer inceleme

  • Emergency playbook: Daemon kontrolü → disk kontrolü → OOM kontrolü → event analizi → restart

  • Debug container: Crashlanan container'ın dosyalarını kopyala, entrypoint override et, sidecar kullan