DevOps & Cloud
Docker Konteyner Rehberi: Dockerfile, Compose ve Multi-Stage Build
Docker, uygulamalarinizi izole konteynerler icerisinde paketleyerek gelistirme, test ve production ortamlari arasindaki tutarsizliklari ortadan kaldirir. Dockerfile ile uygulama imajlarini tanimlar, Docker Compose ile coklu servisleri orkestre eder ve multi-stage build ile production-ready, optimize edilmis imajlar olusturursunuz. Bu yazida Docker konteyner teknolojisinin temellerinden ileri seviye pratiklere kadar kapsamli bir rehber sunacagim.
Kendi projelerimde Docker kullanmaya basladigimdan beri "bende calisiyor" problemini tamamen ortadan kaldirdim. Gelistirme ortamindan production'a kadar tutarli bir calisma ortami saglamak, Docker'in en buyuk avantajlarindan biridir.
Dockerfile: Imaj Olusturma Temelleri
Temel Dockerfile Yapisi
Dockerfile, bir Docker imajinin nasil olusturulacagini tanimlayan talimatlar dosyasidir. Her komut bir katman olusturur ve Docker bu katmanlari onbellegleyerek build surecini hizlandirir.
# .NET 8 API icin optimizasyonlu Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
# Oncelikle proje dosyalarini kopyala (cache optimizasyonu)
COPY ["src/MyApi/MyApi.csproj", "src/MyApi/"]
COPY ["src/MyApi.Domain/MyApi.Domain.csproj", "src/MyApi.Domain/"]
COPY ["src/MyApi.Infrastructure/MyApi.Infrastructure.csproj", "src/MyApi.Infrastructure/"]
RUN dotnet restore "src/MyApi/MyApi.csproj"
# Kaynak kodlari kopyala ve build et
COPY . .
WORKDIR "/src/src/MyApi"
RUN dotnet build "MyApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApi.csproj" -c Release -o /app/publish \
--no-restore \
-p:PublishTrimmed=false \
-p:PublishReadyToRun=true
# Final stage - sadece runtime
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# Non-root kullanici ile calistir
USER $APP_UID
ENTRYPOINT ["dotnet", "MyApi.dll"]Multi-Stage Build Avantajlari
Multi-stage build, imaj boyutunu dramatik sekilde azaltir:
- Build stage: SDK ve tum gelistirme araclarini icerir (~800MB)
- Final stage: Sadece runtime, derlenmis uygulama (~200MB)
- Guvenlik: Build araclari production imajinda bulunmaz
- Hiz: Katman onbellekleme sayesinde tekrar build hizlidir
.dockerignore: Gereksiz Dosyalari Haric Tutma
.dockerignore dosyasi, Docker build context'ine dahil edilmemesi gereken dosyalari tanimlar. Dogru yapilandirilmis bir .dockerignore hem build suresini kisaltir hem de imaja hassas verilerin sizmasini onler.
# .dockerignore
**/bin
**/obj
**/node_modules
**/.git
**/docker-compose*.yml
**/.env
**/.env.*
**/Dockerfile*
*.md
.vs
.vscode
.idea
**/.DS_Store
**/coverage
**/test-results
**/*.user
**/*.log.dockerignore dosyasi olmadan Docker, projedeki tum dosyalari build context'e dahil eder. Ozellikle .git dizini ve node_modules gibi buyuk klasorler, build suresini gereksiz yere uzatir ve imaj boyutunu artirabilir. Production ortaminda .env dosyalarinin build context'e dahil edilmemesi guvenlik acisindan kritiktir.
Docker Compose: Coklu Servis Yonetimi
Docker Compose, birden fazla servisi tek bir YAML dosyasiyla tanimlamanizi ve yonetmenizi saglar. Gelistirme ortamlarinda veritabani, cache, mesaj kuyrugu ve API servislerini birlikte ayaga kaldirmak icin idealdir.
# docker-compose.yml - Full-stack gelistirme ortami
version: '3.8'
services:
api:
build:
context: .
dockerfile: src/MyApi/Dockerfile
ports:
- "5000:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Host=postgres;Database=myapp;Username=postgres;Password=postgres
- Redis__ConnectionString=redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
networks:
- app-network
postgres:
image: postgres:16-alpine
ports:
- "5432:5432"
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
networks:
- app-network
redis:
image: redis:7-alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis-data:/data
networks:
- app-network
pgadmin:
image: dpage/pgadmin4
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@local.dev
PGADMIN_DEFAULT_PASSWORD: admin
depends_on:
- postgres
networks:
- app-network
volumes:
postgres-data:
redis-data:
networks:
app-network:
driver: bridgeDocker Best Practices
Imaj Boyutu Optimizasyonu
Kucuk imajlar daha hizli deploy edilir ve daha az kaynak tuketir:
- Alpine tabanli imajlar kullanin (orn.
node:20-alpine,postgres:16-alpine) - .dockerignore dosyasiyla gereksiz dosyalari haric tutun
- Katman siralamasi: Sik degisen dosyalari Dockerfile'in sonuna koyun
- Multi-stage build: Build araclarini final imajdan cikarin
Guvenlik Pratikleri
- Non-root kullanici: Konteynerleri root olarak calistirmayin
- Belirli tag:
latestyerine spesifik versiyon tag'leri kullanin - Secret yonetimi: Hassas verileri environment variable yerine Docker Secrets veya Vault ile yonetin
- Imaj tarama: Trivy veya Snyk ile guvenlik aciklarini tarayin
Guvenlik Taramasi ile Imaj Dogrulama
Production'a deploy etmeden once Docker imajlarinizi guvenlik acisindan taramak kritik bir adimdir. Trivy, hizli ve kapsamli bir acik kaynak guvenlik tarayicisidir:
# Trivy ile imaj tarama
trivy image myapi:latest
# Sadece CRITICAL ve HIGH severity aciklari goster
trivy image --severity CRITICAL,HIGH myapi:latest
# CI/CD pipeline'inda kullanim - acik bulunursa build'i durdur
trivy image --exit-code 1 --severity CRITICAL myapi:latest
# Dosya sistemi taramasi (Dockerfile olmadan)
trivy fs --security-checks vuln,config .Tarama sonuclarini CI/CD pipeline'iniza entegre ederek guvenlik acigi iceren imajlarin production'a ulasmasi engellenir. Ozellikle base imajlardaki bilinen CVE'leri tespit etmek icin duzenli tarama rutini olusturun.
Saglik Kontrolu (Health Check)
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1Health check, Docker'in konteyner sagligini izlemesini saglar. Ozellikle Docker Compose'da depends_on ile birlikte kullanildiginda, baglantili servislerin hazir olmasini bekleyerek baslangic sorunlarini onler. Production ortaminda health check olmadan calisan konteynerler, hata durumunda otomatik olarak yeniden baslatilmaz ve sessizce servis disi kalabilir.
Docker Network Yonetimi
Docker network'leri, konteynerler arasi iletisimi yonetir. Farkli network turleri farkli senaryolar icin optimize edilmistir:
- Bridge: Varsayilan mod, ayni host uzerindeki konteynerler arasi izole iletisim
- Host: Konteyner dogrudan host ag'ini kullanir, port mapping gerekmez
- Overlay: Docker Swarm modunda birden fazla host arasinda iletisim
- None: Ag erisimi olmadan izole calisma
# Ozel bridge network olustur
docker network create --driver bridge --subnet 172.20.0.0/16 app-network
# Konteyneri belirli bir network'e bagla
docker run -d --name api --network app-network myapi:latest
# Network'deki konteynerleri listele
docker network inspect app-network
# Iki konteyner arasinda baglanti testi
docker exec api ping -c 3 postgresUser-defined bridge network'ler, varsayilan bridge'den farkli olarak DNS-tabanli servis kesfini otomatik olarak destekler. Bu sayede konteynerler birbirine IP yerine isim ile ulasabilir, bu da ozellikle Compose ortaminda buyuk kolaylik saglar.
Docker Volume Yonetimi
Volume'lar, konteyner yasamdongusu disinda veri kaliciligini garanti eder. Uretim ortaminda veritabani verileri, log dosyalari ve yapilandirma dosyalari icin volume kullanimi zorunludur.
# Named volume olustur
docker volume create postgres-data
# Volume ile konteyner baslat
docker run -d --name db \
-v postgres-data:/var/lib/postgresql/data \
postgres:16-alpine
# Volume detaylarini goruntule
docker volume inspect postgres-data
# Kullanilmayan volume'lari temizle
docker volume prune -f
# Volume yedekleme
docker run --rm -v postgres-data:/source -v $(pwd):/backup \
alpine tar czf /backup/postgres-backup.tar.gz -C /source .Gelistirme ortaminda bind mount'lar kaynak kod paylasimi icin kullanilirken, production ortaminda named volume'lar tercih edilmelidir. Bind mount'lar host dosya sistemine bagimlidir ve tasinabilir degildir, ancak gelistirme sirasinda kod degisikliklerinin aninda yansimasi icin idealdir.
Pratik Oneriler ve Ozet
Docker ile calisirken su noktalara dikkat edin:
- Gelistirme/Production paritesi: docker-compose.yml'i gelistirme icin, ayri bir docker-compose.prod.yml'i production icin kullanin
- Log yonetimi: Konteyner loglarini stdout/stderr'e yazdirin, merkezi log toplama araci kullanin
- Kaynak sinirlari:
--memoryve--cpusflag'leri ile konteyner kaynaklarini sinirlandirin - CI/CD entegrasyonu: Docker imajlarini CI pipeline'inda build edip container registry'ye puslayin
- Layer caching: CI'da BuildKit cache'i kullanarak build surelerini kisaltin
Docker, modern yazilim gelistirme surecinin vazgecilmez bir parcasidir. Dogru yapilandirilmis Dockerfile ve Compose dosyalari, hem gelistirme hizinizi artirir hem de deployment sureclerinizi guvenilir kilar.
İlgili Makaleler
AWS Bulut Altyapısı: EC2, S3, CloudFront ve Lambda Rehberi
AWS bulut hizmetlerini öğrenin. EC2 sunucu yönetimi, S3 dosya depolama, CloudFront CDN, Lambda serverless fonksiyonlar ve VPC ağ yapılandırması.
CI/CD Pipeline: GitHub Actions ile Otomatik Test ve Deployment
GitHub Actions ile CI/CD pipeline kurulumu. Otomatik test, build, Docker image oluşturma ve AWS'e deployment.
Kubernetes ile Mikroservis Mimarisi: Pod, Service ve Deployment
Kubernetes ile mikroservis mimarisi. Pod yönetimi, Service discovery, Deployment stratejileri, Ingress ve Helm chart'lar.
Flutter Projeniz mi Var?
iOS, Android ve web için yüksek performanslı Flutter uygulamaları geliştiriyorum.
İletişime Geç