Share
Ağustos 18, 2025

Docker — Gerçekten Derinlemesine ve Öğretici Rehber


İçindekiler (hızlı gezinti)

  1. Docker’ın ne olduğu — kısa ama net
  2. Temel kavramların derin açıklaması (image, container, layer, registry)
  3. Linux altyapısı: namespaces, cgroups, UnionFS (OverlayFS) — nasıl çalışıyor?
  4. Dockerfile derinlemesine — katmanlar, cache, multi-stage, örnekler
  5. Image boyutunu küçültme ve güvenlik
  6. Volumes, bind mounts, tmpfs — veri yönetimi ayrıntıları
  7. Ağ modellemeleri — bridge, host, overlay, macvlan, DNS & service discovery
  8. Güvenlik — en iyi uygulamalar, scanneler, signed images, runtime hardening
  9. Performans optimizasyonu ve kaynak sınırlamaları
  10. Docker Compose ileri kullanım ve ortam ayrıştırma
  11. CI/CD ile Docker (örnek: GitHub Actions + buildx + registry)
  12. Orkestrasyon’a giriş (Kubernetes temelleri — neden, nasıl farklı?)
  13. İzleme, loglama ve gözlemlenebilirlik
  14. Debugging ve yaygın problemler — örnek çözümler
  15. Tasarım desenleri ve gerçek dünya mimarileri
  16. Checklist — production-ready Docker image & deployment
  17. Kaynaklar ve ilerleme önerileri

1 — Docker’ın ne olduğu (özlü tekrar)

Docker, uygulamaları ve bağımlılıklarını katmanlı, taşınabilir image’lar halinde paketleyip, izole runtime (container) üzerinde çalıştırmanı sağlar. Ama önemli olan “neden”: tutarlılık (local = prod), hızlı deploy, daha iyi kaynak izolasyonu ve mikroservis mimarileri için kolaylık.


2 — Temel kavramların derin açıklaması

Image (görüntü)

  • Salt okunur katmanlardan oluşur. Her RUN, COPY vb. adım yeni bir katman (layer) oluşturur.
  • Katmanlar üst üste eklenir; aynı katmanı birçok image paylaşabilir (space/IO avantajı).

Container

  • Image çalıştırılmasıyla oluşan instancedır. Container’ın altında copy-on-write (COW) bir üst katman vardır; container içindekiler değiştikçe bunun içinde tutulur.

Registry

  • Image’ların saklandığı yer (Docker Hub, GitHub Container Registry, GitLab, özel registry). Image push/pull burada olur.

Dockerfile

  • Image yapma tarifidir. Her satır bir katman (çoğu zaman) demektir — iyi yazılmazsa cache ve boyut sorunları çıkar.

3 — Linux altyapısı: namespaces, cgroups, OverlayFS — neden önemli?

Docker “sihir” yapmıyor; Linux kernel özelliklerini kullanıyor:

  • Namespaces: PID, NET, MNT, IPC, UTS, USER gibi namespace’ler ile prosesleri, dosya sistemini, ağını, host adını izole eder. Yani container içindeki PID 1 gerçek host PID’si değildir.
  • cgroups (control groups): CPU, memory, I/O vs sınırlandırılmasını sağlar. --memory, --cpus gibi argümanlar cgroups ile çalışır.
  • Union/OverlayFS: Image katmanlarını tek bir birleşik dosya sistemi gibi sunar. OverlayFS, değişiklikleri üst katmanda tutarak tekrar kullanılabilir alt katmanları korur — bu sayede image’lar hızlı ve hafif olur.

Bu üçlü, Docker’ın izolasyon, performans ve image katman avantajlarını sağlar.


4 — Dockerfile derinlemesine (kural + örnek + anti-pattern)

Neden her satır katman yapar — önemi

Her RUN, COPY, ADD bir katman oluşturur. Bu cache avantajı sağlar ama aşırı katman image boyutunu artırır.

İyi & kötü örnek

Kötü:

FROM ubuntu:22.04
RUN apt update
RUN apt install -y build-essential git
COPY . /app
RUN make /app

(Katman fazla, apt cache temizlenmemiş.)

İyi (tek RUN):

FROM ubuntu:22.04
RUN apt update && apt install -y build-essential git && rm -rf /var/lib/apt/lists/*
COPY . /app
RUN make /app

Multi-stage build (üretim için zorunlu yakın)

Derleme araçlarının olduğu büyük bir image ile sonuçta küçük dağıtım image’ı oluştur:

# build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# runtime
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
CMD ["node", "dist/index.js"]

Bu, final image’ta node_modules sadece production paketleriyle sınırlı tutar; build araçları image’da kalmaz.

.dockerignore kullan

.git, node_modules, *.log gibi gereksiz dosyaları dışarıda bırak; build hızlı olur ve gereksiz katman oluşmaz.


5 — Image boyutunu küçültme & güvenlik

Küçültme taktikleri

  • alpine veya distroless base kullan. (Not: Alpine glibc/ musl farkı yaratabilir; test et.)
  • Multi-stage build kullan.
  • Sıkıştırılmış node_modules yerine production-only kur.
  • --no-install-recommends (apt) kullan.
  • docker-slim gibi araçlarla image’ı optimize et.

Güvenlik

  • Image’ları düzenli tarat (Trivy, Clair, Anchore).
  • Vulnerability patch’leri için base image’ı sık sık güncelle.
  • Image’lara yalnızca gerekli dosyaları koy.
  • Image imzala: cosign ile image signing (supply-chain güvenliği).
  • Immutable tags yerine immutability ile çalış (ör. SHA256 digest).

Örnek tarama komutu (Trivy):

trivy image myregistry/myapp:1.0.0

Image sign örneği (cosign):

cosign sign --key cosign.key myregistry/myapp:1.0.0
cosign verify --key cosign.pub myregistry/myapp:1.0.0

6 — Volumes, bind mounts, tmpfs — veri yönetimi ayrıntıları

  • Bind mount (-v /host/path:/container/path): Host dosya sistemi bağlanır. Geliştirme için ideal (kod üzerinde anında değişiklik).
  • Volume (-v myvol:/path): Docker tarafından yönetilir. Taşınabilirlik ve performans avantajı, backup/snapshot kolaylığı.
  • tmpfs (--tmpfs /cache:rw,size=100m): Bellek tabanlı filesystem — hızlı ama uçucu.

UID/GID uyumsuzluğu: Host ve container kullanıcı id’leri uyuşmazsa permission hatası çıkar. Çözüm: chown ya da kullanıcı eşleştirme (dockerfile içinde USER ile).


7 — Ağ modellemeleri ve DNS

  • bridge (default): İzole ağ, container’lar birbirini isimle keşfeder.
  • host: Container host’un network stack’ini kullanır (düşük latency, daha az izolasyon).
  • overlay: Çok hostlu cluster’lar arası ağ (Swarm/K8s).
  • macvlan: Container’a doğrudan fiziksel ağda IP atamak için (bazı güvenlik/karmaşıklık trade-off’ları var).

Service discovery: Docker DNS (container-name) üzerinden çözüm sağlar. Compose içinde depends_on sıralama sağlar ama readiness kontrolü yapmaz — readiness için healthchecks kullan.


8 — Güvenlik: pratik sıkılaştırma

Build-time

  • Orta katmanda hassas dosya bırakma (örn. .env) yapma.
  • Secrets kullan: Docker Secrets (Swarm) veya daha iyi Vault gibi çözümler.
  • Image’ları yalnızca güvenilen base’lerden oluştur.

Runtime

  • USER kullan: USER appuser ile root olma.
  • Capabilities azalt: --cap-drop=ALL --cap-add=NET_BIND_SERVICE gibi minimal izin ver.
  • seccomp profili: Docker’ın default seccomp iyi ama özelleştirilebilir.
  • read-only filesystem: --read-only ile kök dosya sistemini salt okunur yap, writable alanları tmpfs veya volume ile ver.
  • rm: --rm kısa lived containerlar için disk temizliği sağlar.
  • Network policies: Orkestratörde service-level network policies uygula.

Örnek çalıştırma (güçlendirilmiş):

docker run -d --name myapp \
  --user 1001:1001 \
  --cap-drop=ALL --cap-add=NET_BIND_SERVICE \
  --read-only \
  -v myapp-data:/data:rw \
  --tmpfs /tmp:rw,size=64m \
  myapp:1.0.0

9 — Performans optimizasyonu ve resource management

  • cgroups ile limitler: --memory=512m --cpus=0.5
  • I/O önemi: Disk I/O-bound işlerde SSD, özel volume driver’ları kullan (local SSD, NVMe vs NFS).
  • : Host network belli durumlarda daha hızlı. Ancak güvenlik ve izolasyonu düşün.
  • Katmanları azalt: RUN komutlarını mantıklı birleştir; fakat cache kaybını da göz önünde tut.
  • Build cache: CI’de cache kullan (buildx cache, registry cache) — tekrar build sürelerini kısaltır.

10 — Docker Compose — ileri kullanımlar

Compose sadece local dev değil, test pipeline’ları ve CI’de stack start/stop için güçlü. Yapabileceğin gelişmiş şeyler:

  • .env dosyaları ile ortam ayrıştırma (dev/staging/prod).
  • profiles ile özellikleri toggle etme.
  • depends_on + healthcheck kombinasyonu ile servis ready kontrolü yapma (Compose v3.9+).
  • extends/yığınlar ile ortak base compose dosyası kullanma.

Örnek: healthcheck + depends_on

services:
  db:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      retries: 5

  web:
    build: .
    depends_on:
      db:
        condition: service_healthy

11 — CI/CD ile Docker (pratik örnek: GitHub Actions + buildx + multi-arch)

Neden multi-arch? M1/M2 gibi ARM makineler yaygınlaştı; sunucular x86_64 olabilir. Multi-arch image herkes için çalışır.

Örnek workflow.yml:

name: CI Build & Push

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Login to registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ghcr.io/myorg/myapp:${{ github.sha }}

Bu workflow, multi-arch image’i oluşturur ve registry’e push eder.


12 — Orkestrasyon’a giriş — Docker mı, Kubernetes mi?

Docker tekil host veya küçük cluster’lar için uygundur. Kubernetes:

  • Pod, Deployment, Service, Ingress, StatefulSet gibi abstractions sağlar.
  • Otomatik ölçekleme, self-healing, rolling updates, storage abstraction, network policies.
  • Docker bir runtime iken K8s bir orkestratördür (kubernetes OCI image kullanır). Prod ortamlar genelde bir orkestratör (K8s/Swarm) kullanır.

Kubernetes’e geçerken öğrenmen gerekenler: YAML manifestleri, pod lifecycle, readiness vs liveness probe, configMaps & secrets, persistent volumes, ingress controller, Helm chart’lar.

K8s basit deployment örneği:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels: { app: myapp }
  template:
    metadata:
      labels: { app: myapp }
    spec:
      containers:
      - name: myapp
        image: myregistry/myapp:sha123
        ports:
        - containerPort: 3000
        readinessProbe:
          httpGet: { path: /health, port: 3000 }
          initialDelaySeconds: 5

13 — İzleme, loglama ve gözlemlenebilirlik

  • Loglar: Container logları STDOUT/STDERR‘e yazılmalı. Merkezi toplayıcı (ELK/Elastic, Fluentd, Loki) ile topla.
  • Metrics: Prometheus + node_exporter + cAdvisor + Grafana. cAdvisor konteyner metriklerini sağlar.
  • Tracing: Jaeger veya OpenTelemetry ile request trace’leri topla.

Basit Prometheus + cAdvisor entegrasyonu yerel olarak işe yarar; production’da sidecar pattern veya agent tabanlı collector tercih edilir.


14 — Debugging & yaygın problemler

1. Container başlamıyor:

  • docker logs container → hata çıktılarını kontrol et.
  • docker inspect container → env, mount, network bilgisi.
  • docker exec -it container /bin/sh (veya sh/bash) → içine gir, dosya/dizinleri kontrol et.

2. Permission denied (volume):

  • Host üzerindeki owner/permission container içindeki UID/GID ile uyuşmuyor. Çözüm: chown -R 1001:1001 /host/path veya container içinde kullanıcı eşleme.

3. Network erişimi yok:

  • docker network ls / docker network inspect <network>
  • Port mapping kontrolü: -p hostPort:containerPort.

4. Image çok büyük:

  • docker image history image ile hangi katman büyük onu bul.
  • Multi-stage, cleanup, minimal base.

5. Cache invalidation çok sık:

  • Dockerfile’da bağımlılık kopyalama adımlarını (package.json vb.) kaynak koddan önce koy. Böylece kod değişince tüm bağımlılık yeniden kurulmaz.

15 — Tasarım desenleri & gerçek dünya mimarileri

  • Sidecar: Log toplama, proxy (Envoy), config fetcher gibi görevleri ana container’a yardımcı olarak yan container olarak koş.
  • Ambassador / Adapter: Uygulamayı farklı protokollere adaptörler ile sarmalama.
  • Init container (K8s): Ana container başlamadan önce koşması gereken script/işlemler.
  • Gateway + Service mesh: Ingress + API Gateway + Service Mesh (Istio/Linkerd) = trafik yönetimi, güvenlik, telemetri.
  • Database patterns: StatefulSet + PersistentVolume + Backup/restore stratejileri.

16 — Production-ready checklist (kısa ama kapsamlı)

  • Image: minimal, multi-stage, pinned base, .dockerignore
  • Security: non-root user, capability drop, seccomp/apparmor, secrets yönetimi
  • CI: build, test, scan, sign, push (immutable tag SHA)
  • Healthchecks: liveness & readiness
  • Resource limits: CPU & memory
  • Logging: stdout, central aggregator
  • Monitoring: metrics + alerts
  • Backups: volume snapshot/procedür
  • Network: policies & segmentation
  • Deployment strategy: rolling/canary/blue-green
  • Disaster recovery plan & runbooks

17 — Hızlı cheat-sheet (komutlar)

  • Build: docker build -t myapp:1.0 .
  • Run: docker run -d --name myapp -p 3000:3000 myapp:1.0
  • Exec shell: docker exec -it myapp sh
  • Logs: docker logs -f myapp
  • Images list: docker images
  • Containers list: docker ps -a
  • Inspect: docker inspect myapp
  • Remove: docker rm -f myapp; docker rmi myapp:1.0
  • Volume list: docker volume ls; remove: docker volume rm volname
  • Buildx multi-arch: docker buildx build --platform linux/amd64,linux/arm64 -t myimage:tag --push .

18 — Öğretici Örnek Proje — “Todo API” adım adım (kısa akış)

  1. Proje dizini:
/todo-api
  |- package.json
  |- index.js
  |- Dockerfile
  |- .dockerignore
  |- docker-compose.yml
  1. Dockerfile (multi-stage, Node):
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]
  1. docker-compose (dev):
version: "3.9"
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ./:/app
    environment:
      - NODE_ENV=development
  db:
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=secret
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:
  1. CI pipeline: Build, test, trivy scan, push. (Yukarıdaki GitHub Actions örneği referans.)

19 — İleri seviye notlar (kısa tüyolar)

  • Immutable infrastructure: Container’ları immutably deploy et; konfigürasyon için environment/configMaps kullan.
  • Supply chain security: Image provenance (who built it, hangi commit) için etikets ve imza kullan.
  • Reproducible builds: CI pipeline’ında deterministic build ayarları (cache, reproducible build flags).
  • Local dev ≠ prod: Local compose, prod K8s. Test ortama geçmeden production assumptions’a güvenme.

Sonuç / Ne öğrendin?

Bu yazıda Docker’ın temelinden başlayıp kernel-level izolasyona, Dockerfile optimizasyonuna, güvenlik ve production operasyona kadar geniş bir yelpaze anlattım. Ayrıca pratiğe dökmek için örnek Dockerfile’lar, compose, CI workflow ve production checklist verdim.