
Docker — Gerçekten Derinlemesine ve Öğretici Rehber
İçindekiler (hızlı gezinti)
- Docker’ın ne olduğu — kısa ama net
- Temel kavramların derin açıklaması (image, container, layer, registry)
- Linux altyapısı: namespaces, cgroups, UnionFS (OverlayFS) — nasıl çalışıyor?
- Dockerfile derinlemesine — katmanlar, cache, multi-stage, örnekler
- Image boyutunu küçültme ve güvenlik
- Volumes, bind mounts, tmpfs — veri yönetimi ayrıntıları
- Ağ modellemeleri — bridge, host, overlay, macvlan, DNS & service discovery
- Güvenlik — en iyi uygulamalar, scanneler, signed images, runtime hardening
- Performans optimizasyonu ve kaynak sınırlamaları
- Docker Compose ileri kullanım ve ortam ayrıştırma
- CI/CD ile Docker (örnek: GitHub Actions + buildx + registry)
- Orkestrasyon’a giriş (Kubernetes temelleri — neden, nasıl farklı?)
- İzleme, loglama ve gözlemlenebilirlik
- Debugging ve yaygın problemler — örnek çözümler
- Tasarım desenleri ve gerçek dünya mimarileri
- Checklist — production-ready Docker image & deployment
- 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
veyadistroless
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).
- Ağ: 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ış)
- Proje dizini:
/todo-api
|- package.json
|- index.js
|- Dockerfile
|- .dockerignore
|- docker-compose.yml
- 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"]
- 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:
- 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.