Container'a Bağlanma — exec, attach, logs
Gerçek Hayat Analojisi
Bir uçağın kokpitini düşün. Uçak havadayken pilota ulaşmanın birkaç yolu var: Kontrol kulesinden telsizle konuşabilirsin (logs — sadece dinlersin), kara kutuyu inceleyebilirsin (inspect), veya acil durumda kokpite girip ikinci pilot koltuğuna oturabilirsin (exec). Bir de otopilot paneline direkt bağlanma var — ama dikkatli ol, yanlış bir tuşla uçağı düşürebilirsin (attach).
Docker container'larıyla etkileşimin de benzer yolları var. Bu derste container'a bağlanmanın, içinde komut çalıştırmanın ve logları okumanın tüm yöntemlerini derinlemesine öğreneceğiz.
docker exec — Container İçinde Komut Çalıştırma
docker exec, çalışan bir container'da yeni bir proses başlatır. Container'ın ana prosesini (PID 1) etkilemez. En güvenli ve en sık kullanılan bağlanma yöntemi.
Temel Kullanım
# Çalışan container'da tek komut
docker exec web cat /etc/nginx/nginx.conf
docker exec web ls -la /app/
docker exec web env
docker exec web whoami
docker exec web hostname
docker exec web date
# Komut çıktısını al
docker exec web cat /var/log/nginx/error.log > local-error.logİnteraktif Shell Açma
# Bash shell aç (Debian/Ubuntu tabanlı image'larda)
docker exec -it web bash
# sh shell aç (Alpine tabanlı image'larda — bash yok!)
docker exec -it web sh
# Zsh shell (yüklüyse)
docker exec -it web zsh
# -i = interactive (stdin açık tutar)
# -t = TTY (terminal emülatörü — renk, satır düzeni)
# İkisi birlikte: interaktif terminal oturumuFlag'ler Detaylı
# -i (interactive) — stdin açık tutar
docker exec -i web cat
# Metin yazabilirsin, Ctrl+D ile bitir
# -t (tty) — pseudo-terminal tahsis eder
docker exec -t web top
# top komutu düzgün görünür (ama Ctrl+C çalışmaz)
# -it (ikisi birlikte) — tam interaktif terminal
docker exec -it web bash
# Tam fonksiyonel shell oturumu
# -d (detached) — arka planda çalıştır
docker exec -d web touch /tmp/marker
# Sonucu bekleme, hemen dön
# -e (environment) — ek ortam değişkeni
docker exec -e DEBUG=true -e LOG_LEVEL=verbose web env | grep -E "DEBUG|LOG"
# DEBUG=true
# LOG_LEVEL=verbose
# -u (user) — farklı kullanıcı ile çalıştır
docker exec -u root web apt-get update # root olarak
docker exec -u nobody web whoami # nobody olarak
docker exec -u 1000:1000 web id # UID:GID ile
# -w (workdir) — çalışma dizini belirle
docker exec -w /etc/nginx web ls -la
# nginx config dizininde ls çalışırPratik exec Kullanımları
# === Debugging ===
# Dosya sistemi kontrolü
docker exec web ls -la /app/
docker exec web find /app -name "*.log" -size +1M
# Network durumu
docker exec web ss -tlnp
docker exec web cat /etc/resolv.conf
docker exec web ping -c 3 database
docker exec web wget -qO- http://api:3000/health
# Process listesi
docker exec web ps aux
docker exec web top -bn1 | head -20
# Disk kullanımı
docker exec web df -h
docker exec web du -sh /app/ /var/log/ /tmp/
# Memory kullanımı
docker exec web free -h
docker exec web cat /proc/meminfo | head -5
# === Dosya İşlemleri ===
# Dosya oluştur/düzenle
docker exec web sh -c 'echo "new content" > /tmp/test.txt'
docker exec web sed -i 's/old/new/g' /app/config.json
# Dosya oku
docker exec web cat /app/config.json | jq .
docker exec web head -50 /var/log/app.log
# === Veritabanı İşlemleri ===
# PostgreSQL
docker exec -it db psql -U postgres
docker exec db psql -U postgres -c "SELECT count(*) FROM users;"
# MySQL
docker exec -it db mysql -u root -p
docker exec db mysql -u root -psecret -e "SHOW DATABASES;"
# Redis
docker exec -it redis redis-cli
docker exec redis redis-cli INFO memory
# MongoDB
docker exec -it mongo mongosh
docker exec mongo mongosh --eval "db.stats()"exec ile Script Çalıştırma
# Container'a script gönder ve çalıştır
docker exec -i web sh << 'EOF'
echo "=== System Info ==="
uname -a
echo ""
echo "=== Disk Usage ==="
df -h /
echo ""
echo "=== Memory ==="
free -h
echo ""
echo "=== Processes ==="
ps aux | head -10
EOF
# Host'taki script'i container'da çalıştır
docker exec -i web sh < ./debug-script.shdocker attach — Container'ın Ana Prosesine Bağlanma
docker attach, container'ın PID 1 prosesinin stdout/stderr/stdin'ine bağlanır. Yeni proses oluşturmaz — mevcut ana prosese "takılır".
Temel Kullanım
# Container'ın çıktısını izle
docker attach web
# Çıktı akmaya başlar:
# 172.17.0.1 - - [15/Jan/2024:10:30:00 +0000] "GET / HTTP/1.1" 200 612
# 172.17.0.1 - - [15/Jan/2024:10:30:01 +0000] "GET /favicon.ico HTTP/1.1" 404 153⚠️ Attach Tehlikeleri
# TEHLİKE 1: Ctrl+C container'ı DURDURUR
docker attach web
# Ctrl+C basarsan → SIGTERM → container durur!
# Güvenli çıkış: detach sequence
# Ctrl+P, sonra Ctrl+Q → sadece bağlantıyı keser, container çalışmaya devam eder
# TEHLİKE 2: stdin bağlıysa input gönderilebilir
docker attach web
# Yazdığın her şey PID 1'in stdin'ine gider
# Bazı uygulamalar beklenmedik input'la crash olabilirGüvenli Attach
# Sadece stdout izle (stdin gönderme, sinyal gönderme)
docker attach --no-stdin --sig-proxy=false web
# Ctrl+C sadece attach'i keser, container'ı durdurmaz
# Bu aslında docker logs -f'e benzer ama farklı mekanizma
# Detach keys'i özelleştir
docker attach --detach-keys="ctrl-x" web
# Ctrl+X ile çıkarsın (varsayılan Ctrl+P, Ctrl+Q yerine)exec vs attach Karşılaştırma
| Özellik | docker exec | docker attach |
|---|---|---|
| Ne yapar | Yeni proses başlatır | PID 1'e bağlanır |
| Proses sayısı | +1 yeni proses | Mevcut proses |
| PID 1'i etkiler | ❌ Hayır | ✅ Evet |
| Ctrl+C etkisi | Exec prosesini kapatır | Container'ı durdurur! |
| Güvenlik | Güvenli | Riskli |
| Kullanım alanı | Debug, komut çalıştırma | Log izleme (dikkatli) |
| Çoklu oturum | Birden fazla exec açılabilir | Aynı anda birden fazla attach sorunlu |
Kural: %99 durumda docker exec kullan. docker attach sadece çok özel durumlarda ve --no-stdin --sig-proxy=false flag'leriyle.
docker logs — Container Loglarını Okuma
Container'lar stdout ve stderr'e yazdıkları her şeyi loglar. docker logs bu logları okur.
Temel Kullanım
# Tüm loglar
docker logs web
# 172.17.0.1 - - [15/Jan/2024:10:30:00 +0000] "GET / HTTP/1.1" 200 612
# 172.17.0.1 - - [15/Jan/2024:10:30:05 +0000] "GET /api/users HTTP/1.1" 200 1234
# 2024/01/15 10:30:10 [error] open() "/usr/share/nginx/html/missing" failed
# Son N satır
docker logs --tail 20 web
docker logs --tail 100 web
docker logs --tail 0 web # Hiçbir eski log gösterme
# Canlı takip (follow)
docker logs -f web
# Yeni loglar anında görünür (Ctrl+C ile çık)
# Son N satır + canlı takip (en yaygın kullanım)
docker logs --tail 50 -f webZaman Bazlı Filtreleme
# Belirli zamandan sonraki loglar
docker logs --since "2024-01-15T10:00:00" web
docker logs --since "2024-01-15" web
# Göreceli zaman
docker logs --since 1h web # Son 1 saat
docker logs --since 30m web # Son 30 dakika
docker logs --since 5s web # Son 5 saniye
docker logs --since 2h30m web # Son 2.5 saat
# Belirli zamana kadar
docker logs --until 5m web # 5 dakika öncesine kadar
docker logs --until "2024-01-15T11:00:00" web
# Zaman aralığı
docker logs --since 1h --until 30m web # 1 saat - 30 dk öncesi arası
# Zaman damgası ile göster
docker logs -t web
# 2024-01-15T10:30:00.123456789Z 172.17.0.1 - - "GET / HTTP/1.1" 200
# 2024-01-15T10:30:05.234567890Z 172.17.0.1 - - "GET /api HTTP/1.1" 200Log Analizi
# Hata loglarını filtrele
docker logs web 2>&1 | grep -i "error"
docker logs web 2>&1 | grep -i "warn\|error\|fatal"
# HTTP status code dağılımı
docker logs web 2>&1 | grep -oP '" \K[0-9]{3}' | sort | uniq -c | sort -rn
# 1523 200
# 234 304
# 45 404
# 3 500
# Son 1 saatteki hata sayısı
docker logs --since 1h web 2>&1 | grep -c "error"
# IP bazlı erişim sayısı
docker logs web 2>&1 | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# 523 172.17.0.1
# 234 10.0.0.5
# 45 192.168.1.100
# Logları dosyaya kaydet
docker logs web > /tmp/web-stdout.log 2> /tmp/web-stderr.log
# veya hepsini tek dosyaya
docker logs web > /tmp/web-all.log 2>&1Log Driver'ları
Docker logları farklı hedeflere yönlendirebilir:
# Varsayılan: json-file
docker run -d --log-driver json-file --name web nginx
# Log dosyasının fiziksel konumu
docker inspect web --format '{{.LogPath}}'
# /var/lib/docker/containers/<id>/<id>-json.log
# Log dosyasını direkt oku
sudo cat $(docker inspect web --format '{{.LogPath}}') | jq .
# {"log":"172.17.0.1 - - ...\n","stream":"stdout","time":"2024-01-15T10:30:00.123Z"}Log Boyut Limitleri
# ⚠️ Docker logları varsayılanda SINIRSIZ büyür!
# Production'da log rotation zorunlu
# Container bazında limit
docker run -d \
--log-opt max-size=10m \
--log-opt max-file=3 \
--name web nginx
# Her log dosyası max 10MB, max 3 dosya tutulur
# Toplam: max 30MB log
# Global ayar (tüm container'lar için)
# /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
sudo systemctl restart docker
# Mevcut log boyutunu kontrol et
du -sh $(docker inspect web --format '{{.LogPath}}')
# 5.2M /var/lib/docker/containers/.../...-json.logFarklı Log Driver'ları
# syslog
docker run -d --log-driver syslog \
--log-opt syslog-address=udp://logserver:514 \
--name web nginx
# fluentd
docker run -d --log-driver fluentd \
--log-opt fluentd-address=fluentd:24224 \
--name web nginx
# awslogs (AWS CloudWatch)
docker run -d --log-driver awslogs \
--log-opt awslogs-region=eu-west-1 \
--log-opt awslogs-group=myapp \
--log-opt awslogs-stream=web \
--name web nginx
# none (log yok — performans için)
docker run -d --log-driver none --name web nginx
# ⚠️ docker logs çalışmaz!docker cp — Dosya Kopyalama
Container ile host arasında dosya kopyalamak için:
# === Container → Host ===
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
docker cp web:/var/log/nginx/ ./logs/
docker cp web:/app/data/export.csv ./export.csv
# === Host → Container ===
docker cp ./custom.conf web:/etc/nginx/conf.d/custom.conf
docker cp ./data/ web:/app/data/
docker cp ./script.sh web:/tmp/script.sh
# Durmuş container'dan da çalışır!
docker stop web
docker cp web:/var/log/nginx/error.log ./error.log
# Pipe ile
docker cp web:/app/data/users.json - | jq '.[] | .name'
# stdin'den de çalışır
echo "Hello" | docker cp - web:/tmp/hello.txtDosya Kopyalama vs Volume
# docker cp: Tek seferlik kopyalama, debug/rescue
# Volume: Kalıcı paylaşım, geliştirme/production
# Geliştirmede: bind mount kullan
docker run -v $(pwd)/src:/app/src web
# Debug'da: docker cp kullan
docker cp web:/var/log/app/error.log ./docker top — Container Prosesleri
# Container'daki prosesleri listele
docker top web
# UID PID PPID CMD
# root 12345 12344 nginx: master process nginx -g daemon off;
# nginx 12346 12345 nginx: worker process
# nginx 12347 12345 nginx: worker process
# nginx 12348 12345 nginx: worker process
# nginx 12349 12345 nginx: worker process
# ps formatıyla
docker top web aux
# USER PID %CPU %MEM VSZ RSS COMMAND
# root 1 0.0 0.1 10652 5432 nginx: master process
# nginx 29 0.0 0.0 11088 2648 nginx: worker process
# Özel format
docker top web -eo pid,comm,rss,vsz
# PID COMMAND RSS VSZ
# 1 nginx 5432 10652
# 29 nginx 2648 11088docker diff — Dosya Değişiklikleri
Container'da değiştirilen dosyaları gösterir:
docker diff web
# C /var ← Changed (değişti)
# C /var/cache
# C /var/cache/nginx
# A /var/cache/nginx/client_temp ← Added (eklendi)
# C /run
# A /run/nginx.pid ← Added (eklendi)
# A = Added, C = Changed, D = Deleteddocker wait — Container'ın Bitmesini Bekle
# Container durana kadar bekle ve exit code'u al
docker wait mycontainer
# 0 (başarılı)
# veya 1, 137, vb. (hata)
# Script'te kullanım
docker run -d --name job myapp python process.py
EXIT_CODE=$(docker wait job)
if [ $EXIT_CODE -eq 0 ]; then
echo "Job succeeded!"
docker cp job:/output/result.csv ./result.csv
else
echo "Job failed with code $EXIT_CODE"
docker logs job > error.log
fi
docker rm jobGerçek Dünya Senaryosu: Production Debugging Workflow
Bir production container'da sorun var. Adım adım debug edelim:
# 1. Container durumunu kontrol et
docker ps -a --filter name=api
# STATUS: Up 5 hours (unhealthy)
# 2. Son logları incele
docker logs --tail 100 api 2>&1 | grep -i "error\|warn\|exception"
# 2024-01-15 10:30:00 ERROR Database connection timeout
# 2024-01-15 10:30:15 WARN Retry attempt 3/5
# 3. Sağlık kontrolü detayı
docker inspect api --format '{{json .State.Health}}' | jq .
# {
# "Status": "unhealthy",
# "FailingStreak": 5,
# "Log": [
# {"ExitCode": 1, "Output": "curl: connection refused"}
# ]
# }
# 4. Container'a gir ve araştır
docker exec -it api sh
# İçeride:
# Network kontrol
ping -c 2 database # DB erişimi var mı?
wget -qO- http://localhost:3000/health # Health endpoint
# Config kontrol
cat /app/.env # Environment değişkenleri doğru mu?
env | grep DATABASE # DB bağlantı bilgisi
# Disk kontrol
df -h # Disk dolu mu?
du -sh /var/log/ /tmp/ # Log birikiyor mu?
# Process kontrol
ps aux # Zombi proses var mı?
top -bn1 # CPU/memory kullanımı
exit
# 5. Resource kullanımını kontrol et
docker stats --no-stream api
# CPU: 95% MEM: 490MiB/512MiB ← Memory limitine yakın!
# 6. Config dosyalarını çek ve incele
docker cp api:/app/config.json ./debug-config.json
cat debug-config.json | jq .
# 7. Çözüm: Container'ı restart et (geçici) veya fix deploy et
docker restart api
docker logs --tail 20 -f api # Restart sonrası logları izleDebug Toolkit Container
Bazı production image'larda (distroless gibi) debug araçları yok. Sidecar container kullanarak debug yapabilirsin:
# Debug toolkit image'ı
docker run -it --rm \
--network container:api \
--pid container:api \
nicolaka/netshoot \
bash
# Bu container:
# - api ile aynı network namespace'i paylaşır (aynı IP, portlar)
# - api ile aynı PID namespace'i paylaşır (proseslerini görebilir)
# - curl, dig, nslookup, tcpdump, strace, htop... hepsi var
# İçeride:
curl localhost:3000/health # API'nin health endpoint'i
dig database # DNS çözümleme
tcpdump -i eth0 port 5432 -c 10 # DB trafiğini izle
ss -tlnp # Açık portlar
htop # Kaynak kullanımı (api proseslerini de görür)Monitoring Script Örneği
#!/bin/bash
# container-monitor.sh — Container sağlık izleme
CONTAINERS=("web" "api" "db" "redis")
while true; do
clear
echo "=== Container Monitor === $(date)"
echo ""
for CONTAINER in "${CONTAINERS[@]}"; do
STATUS=$(docker inspect $CONTAINER --format '{{.State.Status}}' 2>/dev/null)
if [ "$STATUS" = "running" ]; then
HEALTH=$(docker inspect $CONTAINER --format '{{.State.Health.Status}}' 2>/dev/null || echo "N/A")
CPU=$(docker stats --no-stream --format '{{.CPUPerc}}' $CONTAINER)
MEM=$(docker stats --no-stream --format '{{.MemUsage}}' $CONTAINER)
if [ "$HEALTH" = "healthy" ] || [ "$HEALTH" = "N/A" ]; then
echo "✅ $CONTAINER: $STATUS ($HEALTH) | CPU: $CPU | MEM: $MEM"
else
echo "⚠️ $CONTAINER: $STATUS ($HEALTH) | CPU: $CPU | MEM: $MEM"
echo " Last errors:"
docker logs --tail 3 $CONTAINER 2>&1 | grep -i "error" | sed 's/^/ /'
fi
else
echo "❌ $CONTAINER: $STATUS"
fi
done
echo ""
echo "Press Ctrl+C to exit. Refreshing in 10s..."
sleep 10
doneBest Practices
✅ Yap:
Debug için her zaman `docker exec -it` kullan
Log'larda `--tail N -f` ile son logları canlı takip et
Log rotation ayarla (
max-size,max-file) — disk dolmasını önle`docker stats` ile kaynak kullanımını düzenli izle
Production'da log driver yapılandır (syslog, fluentd, cloudwatch)
Debug toolkit container kullan (netshoot) — minimal image'larda
❌ Yapma:
`docker attach` kullanarak yanlışlıkla container durdurma
Log rotation olmadan container çalıştırma (disk dolar!)
docker exec -it container bashsonra çıkmayı unutma (kaynak israfı)Container içinde kalıcı değişiklik yapma (restart'ta kaybolur — Dockerfile/volume kullan)
--log-driver nonekullanma (sorun olunca log yoktur)
Yaygın Hatalar ve Çözümleri
Hata 1: "OCI runtime exec failed: exec failed: container_linux.go: unable to start container process: exec: 'bash': executable file not found"
docker exec -it web bash
# exec: "bash": executable file not found
# Alpine image'larda bash yok — sh kullan
docker exec -it web sh
# Veya bash kur (kalıcı olması için Dockerfile'a ekle)
docker exec -u root web apk add --no-cache bashHata 2: Container logları çok büyük — disk dolu
# Log dosyası boyutunu kontrol et
sudo du -sh /var/lib/docker/containers/*/
# 15G /var/lib/docker/containers/abc123.../
# Acil çözüm: Log dosyasını truncate et
sudo truncate -s 0 $(docker inspect web --format '{{.LogPath}}')
# Kalıcı çözüm: Log rotation ekle
docker run -d --log-opt max-size=10m --log-opt max-file=3 ...Hata 3: docker exec "is not running" hatası
docker exec web ls
# Error: container is not running
# Container durmuş
docker ps -a --filter name=web
# STATUS: Exited (1) 5 minutes ago
# Çözüm: Önce başlat
docker start web
docker exec web ls
# Veya loglardan neden durduğunu anla
docker logs --tail 50 webHata 4: Attach'ten çıkamıyorum
# Ctrl+C basınca container da durdu!
# Ctrl+P, Ctrl+Q ile detach etmeliydin
# Bir sonraki sefere güvenli attach:
docker attach --no-stdin --sig-proxy=false web
# veya docker logs -f kullanÖzet
`docker exec` container'da yeni proses başlatır — debug, komut çalıştırma, DB bağlantısı için birinci tercih
`docker attach` PID 1'e bağlanır — tehlikeli (Ctrl+C container'ı durdurur),
--no-stdin --sig-proxy=falseile kullan`docker logs` stdout/stderr loglarını okur —
--tail,--since,-f,-tflag'leri hayat kurtarırLog rotation zorunlu:
--log-opt max-size=10m --log-opt max-file=3— aksi takdirde disk dolar`docker cp` container ile host arasında dosya kopyalar — debug ve rescue operasyonları için
Production debugging'de netshoot gibi toolkit container'ları kullan — minimal image'larda bile debug yapabilirsin
AI Asistan
Sorularını yanıtlamaya hazır