"Benim makinemde çalışıyordu" cümlesi, dağıtık sistemlerde geliştirme verimliliğini öldüren en pahalı cümlelerden biridir. Docker Compose, uygulama servislerini, veritabanlarını, mesaj kuyruklarını ve ağ topolojisini tek bir bildirim dosyasında tanımlayarak her geliştiricinin aynı bağımlılık grafını saniyeler içinde ayağa kaldırmasını sağlar. Compose bir orkestratör değildir; yerel geliştirme ve entegrasyon testleri için tasarlanmış bir "altyapı as code" aracıdır ve bu sınırı doğru anlamak tasarım kararlarını netleştirir.
Compose dosyasının rolü
compose.yaml dosyası, servisler arası sözleşmeyi versiyon kontrolüne alır. PostgreSQL sürümü, Redis portu, API'nin hangi ortam değişkenleriyle başlayacağı ve servisler arası DNS adları kod review sürecine girer. Yeni bir geliştirici repoyu klonladıktan sonra docker compose up -d ile üretime yakın bir ortam elde eder; kurulum dokümanındaki on beş adımlık manuel rehber ortadan kalkar.
services:
api:
build:
context: .
dockerfile: Dockerfile
target: development
ports:
- "8080:8080"
environment:
ConnectionStrings__Default: Host=db;Port=5432;Database=app;Username=app;Password=dev
Redis__Host: redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./src:/app/src:cached
develop:
watch:
- action: sync
path: ./src
target: /app/src
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: dev
POSTGRES_DB: app
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 3s
retries: 5
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
command: redis-server --save "" --appendonly no
volumes:
pgdata:
Servis bağımlılık sırası
depends_on tek başına bir servisin hazır olduğunu garanti etmez; yalnızca başlatma sırasını etkiler. Veritabanı konteyneri ayakta olsa bile PostgreSQL bağlantı kabul etmeye hazır olmayabilir. condition: service_healthy ile healthcheck tanımlamak, API'nin erken bağlantı hatalarıyla çökmesini önler. Uygulama tarafında retry ve exponential backoff yine de önerilir; Compose sağlık kontrolü ile uygulama dayanıklılığı birbirini tamamlar.
Profiller ve ortam ayrımı
Compose v2 profilleri, aynı repoda farklı geliştirici senaryolarını yönetmek için kullanılır. Örneğin observability profili Grafana ve Prometheus içerir; günlük geliştirmede devreye alınmaz:
prometheus:
image: prom/prometheus:v2.52.0
profiles: ["observability"]
volumes:
- ./ops/prometheus.yml:/etc/prometheus/prometheus.yml:ro
docker compose --profile observability up komutu yalnızca ilgili servisleri ekler. .env dosyası ile port çakışmalarını geliştirici bazında çözebilirsiniz; .env.example repoda versiyonlanır, gerçek .env gitignore'da kalır.
Hot reload ve geliştirici deneyimi
Bind mount (volumes: ./src:/app/src) kaynak kod değişikliklerini konteynere yansıtır; ancak Windows ve macOS'ta dosya sistemi gecikmesi yaşanabilir. :cached veya :delegated bayrakları performansı iyileştirir. Compose Watch (Docker Desktop 4.24+) ile dosya değişikliklerinde otomatik sync veya rebuild tetiklenir; dotnet watch, nodemon veya air gibi araçlar konteyner içinde çalıştırılır.
- Development target: Multi-stage Dockerfile'da SDK içeren ayrı bir
developmentstage tanımlayın. - Production parity: Yerel ortam runtime sürümünü üretimle eşleştirin; "16-alpine" yerel, "15" üretim felakete davetiye çıkarır.
- Seed verisi:
docker-entrypoint-initdb.dile PostgreSQL ilk açılışta seed SQL çalıştırın.
Ağ ve servis keşfi
Compose varsayılan olarak proje adına göre izole bir bridge ağı oluşturur. Servis adları DNS kaydı gibi çözülür: API, http://auth:8080 ile kimlik servisine erişir. Harici sistemleri taklit etmek için mock servisler eklemek entegrasyon testlerini hızlandırır. Traefik veya nginx reverse proxy servisi tanımlayarak yerelde TLS termination ve path-based routing deneyebilirsiniz; bu, Kubernetes Ingress davranışını yaklaşık olarak simüle eder.
Veri kalıcılığı ve temizlik
Named volume (pgdata) veritabanı verisini konteyner yeniden oluşturmalarında korur. docker compose down -v tüm volume'leri siler; dokümantasyonda bu komutun veri kaybına yol açtığı açıkça belirtilmelidir. Geliştiriciler için make reset-db gibi güvenli sarmalayıcı komutlar, yanlışlıkla üretim benzeri veriyi silmeyi zorlaştırır.
CI'da Compose kullanımı
Entegrasyon test job'ları Compose ile tüm stack'i ayağa kaldırır, testleri çalıştırır ve kapatır:
docker compose -f compose.yaml -f compose.ci.yaml up --abort-on-container-exit --exit-code-from tests
compose.ci.yaml override dosyası, port publish etmeden servisleri internal ağda tutar ve test konteynerini ekler. --wait bayrağı healthcheck tamamlanana kadar bekler. Test sonrası docker compose down -v --remove-orphans runner'ı temizler.
Güvenlik ve gizli bilgiler
Compose dosyasında gerçek üretim parolaları asla bulunmamalıdır. Yerel geliştirme için zayıf ama bilinen parolalar kabul edilebilir; ancak bu dosyaların yanlışlıkla paylaşılmaması gerekir. Docker secrets (Swarm modunda) veya harici secret manager entegrasyonu üretim Compose senaryolarında tercih edilir. env_file ile hassas değerleri ayırın ve CI'da GitHub Actions secrets ile enjekte edin.
Performans ve kaynak sınırları
Yerel makinede on servis aynı anda çalıştırmak RAM baskısı oluşturur. deploy.resources.limits (Swarm/Kubernetes benzeri modlarda) veya Docker Desktop kaynak ayarları ile sınırlar konulmalıdır. Gereksiz servisleri profille devre dışı bırakmak, laptop pil ömrünü ve derleme hızını doğrudan etkiler.
Compose vs alternatifler
Tilt, DevSpace ve Skaffold Kubernetes'e yönelik geliştirme döngüsünü hızlandırır; Compose ise daha hafif ve öğrenmesi kolaydır. Küçük ve orta ekipler için Compose yeterlidir; mikroservis sayısı 20'yi geçtiğinde partial stack veya remote development cluster düşünülür. Testcontainers kütüphanesi, JUnit veya xUnit testlerinde geçici konteynerler ayağa kaldırarak Compose'suz izole test imkanı verir; ikisi birbirini dışlamaz.
Operasyonel disiplin
- Compose dosyasını lint edin:
docker compose configsözdizimini doğrular. - Sürüm pinleyin:
postgres:16-alpineyerine digest ile sabitleyin kritik ortamlarda. - README'de minimum Docker sürümünü belirtin.
- Breaking değişikliklerde migration notu ekleyin.
Compose ile yerel ortam, DevOps kültürünün en erişilebilir uygulamalarından biridir. Altyapıyı kod olarak tanımlamak, ekip onboarding süresini günlerden saatlere indirir; healthcheck, profil ve CI override kalıpları olgunlaştıkça yerel-üretim parity hedefi gerçekçi biçimde yakalanır.
Override dosyaları ve kompozisyon
docker compose -f compose.yaml -f compose.override.yaml kalıbı, temel stack ile geliştiriciye özel ayarları birleştirir. Override dosyası gitignore'da tutulabilir; kişisel port eşlemeleri veya ek debug servisleri burada tanımlanır. compose.ci.yaml ise port publish etmez, ephemeral volume kullanır ve test konteynerini ekler. Merge kuralları: mapping'ler birleşir, sequence'lar override edilir, scalar değerler son dosyada kazanır.
Ağ modları
Varsayılan bridge ağı çoğu senaryo için yeterlidir. Host network modu düşük gecikme gerektiren performans testlerinde kullanılır ancak port çakışması riski taşır. Harici ağ tanımı (external: true) ile mevcut bir reverse proxy ağına bağlanmak, yerelde microservice mesh simülasyonu sağlar. Servisler arası TLS için mkcert ile yerel sertifika üretip volume mount etmek, production TLS davranışını test etmenin pratik yoludur.
Sorun giderme ve günlük akış
docker compose logs -f api ile tek servis logu takip edilir; docker compose ps health durumunu gösterir. Servis sürekli restart ediyorsa genellikle migration hatası, eksik env veya readiness gecikmesi vardır. docker compose exec db psql -U app ile veritabanına doğrudan bağlanmak seed veya migration sorunlarını ayıklamayı hızlandırır. Makefile veya justfile ile sık komutları sarmalamak (just up, just reset, just logs api) ekip genelinde tutarlılık sağlar.
Üretim Compose farkları
Üretimde Compose yerine genellikle Kubernetes veya managed PaaS tercih edilir; ancak küçük self-hosted senaryolarda Compose Swarm veya Docker Compose production modları kullanılabilir. Üretim Compose dosyasında resource limit, restart policy (unless-stopped), log driver ve read-only root filesystem tanımlanmalıdır. Yerel dosya ile üretim dosyasını ayırmak, geliştirici kolaylığını operasyonel güvenlikten izole eder.