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 etDocker 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>&1Container İ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 limitGerç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 statsEvent'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 1hSorun 1: Container Başlamıyor
Exit Code Analizi
docker inspect myapp --format '{{.State.ExitCode}}'| Exit Code | Anlamı | Yaygın Sebep | Çözüm |
|---|---|---|---|
| 0 | Normal çıkış | CMD tamamlandı | CMD'nin sürekli çalışan bir process olduğundan emin ol |
| 1 | Uygulama hatası | Kod hatası, eksik config | Log'lara bak, env değişkenlerini kontrol et |
| 126 | Permission denied | Çalıştırılabilir değil | chmod +x veya doğru user |
| 127 | Command not found | Yanlış CMD/ENTRYPOINT | Dockerfile'ı kontrol et |
| 137 | SIGKILL (OOM) | Bellek limiti aşıldı | Memory limit artır |
| 139 | SIGSEGV | Segmentation fault | Uygulama bug'ı, native lib sorunu |
| 143 | SIGTERM | Graceful shutdown | Normal — 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 yapContainer 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.jarContainer "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örSorun 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 myappMemory 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 dbContainer'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'iSorun 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 --purgeSorun 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 -fDockerfile 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 inceleyebilirsinSorun 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_healthyEnvironment 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 configVolume 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 -- bashDocker 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 shEmergency 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 -dSenaryo 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 myappSenaryo 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 dbBest 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 execile düzeltme — yeni image build etProduction'da
-f(force) flag'ini düşünmeden kullanmadocker system prune --volumeskomutunu production'da alışkanlık yapmaLog 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 rotasyonuBuild debug:
--progress=plain, stage'de durdurma, intermediate layer incelemeEmergency playbook: Daemon kontrolü → disk kontrolü → OOM kontrolü → event analizi → restart
Debug container: Crashlanan container'ın dosyalarını kopyala, entrypoint override et, sidecar kullan
AI Asistan
Sorularını yanıtlamaya hazır