aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Araçlar & DevOps

Docker Compose ile Çok Servisli Uygulama Kurma

Docker Compose, birden fazla konteyneri tek bir YAML dosyasında tanımlayıp tek komutla ayağa kaldırmanı sağlayan araçtır. Gerçek bir uygulama nadiren tek bir süreçten oluşur: bir web sunucusu, bir veritabanı ve çoğu zaman bir cache katmanı birlikte çalışır. Bunları tek tek docker run ile başlatmak hem yorucu hem de hataya açıktır. Bu yazıda web, PostgreSQL ve Redis servislerinden oluşan tipik bir yığını sıfırdan kuracak; servisler arası iletişim, kalıcı veri ve ortam değişkenleri gibi konuları pratik örneklerle göreceğiz.

Docker Compose neyi çözer?

Tek bir konteyner çalıştırmak kolaydır, ama gerçek projelerde işler hızla karmaşıklaşır. Her servisin kendi imajı, portu, ağı ve ortam değişkenleri vardır; üstelik bunların belirli bir sırada ayağa kalkması gerekir. Compose bu karmaşıklığı bildirimsel (declarative) bir dosyaya taşır:

  • Tek kaynak: Tüm yığın compose.yaml içinde tanımlıdır; ekibe arkadaşın repoyu klonlar ve docker compose up yazar.
  • Otomatik ağ: Compose servisler için ortak bir ağ kurar; konteynerler birbirine servis adıyla ulaşır.
  • Tekrarlanabilirlik: Aynı dosya, geliştirici makinesinde de CI ortamında da aynı yığını üretir.

Not: Modern Docker sürümlerinde komut docker compose (boşluklu) biçimindedir; eski docker-compose (tireli) ikilisi hâlâ çalışsa da Compose V2 ile birlikte tireli sürüm yerini almıştır.

İlk compose.yaml dosyası

Bir klasör açıp içine compose.yaml oluşturalım. Önce sadece bir web servisi ve bir veritabanı tanımlayalım:

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: appdb
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Birkaç önemli ayrıntı: ports altındaki "8080:80" ifadesi, host makinedeki 8080 portunu konteynerin 80 portuna bağlar. depends_on web servisinin db'den sonra başlamasını sağlar (ancak db'nin hazır olmasını garanti etmez — buna birazdan döneceğiz). volumes ise veritabanı dosyalarını konteyner silinse bile koruyan kalıcı bir birim oluşturur.

Cache katmanı ekleme: Redis

Çoğu uygulama oturum, kuyruk veya önbellek için Redis kullanır. Üçüncü bir servis eklemek tek bir blok meselesidir:

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    depends_on:
      - db
      - cache

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: appdb
    volumes:
      - db-data:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    command: ["redis-server", "--save", "60", "1"]

volumes:
  db-data:

Burada güzel olan şu: web konteyneri içinden veritabanına db, Redis'e ise cache hostname'i üzerinden erişilir. Compose'un kurduğu dahili DNS, servis adını otomatik olarak doğru IP'ye çözer. Yani uygulama yapılandırmanda bağlantı dizesi postgres://app:secret@db:5432/appdb ve redis://cache:6379 biçiminde olur — sabit IP yazmana gerek yok.

Ortam değişkenleri ve .env dosyası

Parolaları YAML'a gömmek iyi bir fikir değildir. Compose, yanındaki .env dosyasını otomatik okur ve değişkenleri ${...} sözdizimiyle yerine koyar:

# .env
POSTGRES_PASSWORD=cok-gizli-bir-deger
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: appdb

.env dosyasını .gitignore'a ekleyerek sırların depoya girmesini engelle. Ekibin geri kalanı için örnek bir .env.example bırakmak iyi bir alışkanlıktır.

Sağlık kontrolü ile gerçek hazır olma

depends_on yalnızca başlatma sırasını belirler; veritabanının bağlantı kabul ettiğini garanti etmez. Web servisi, db daha açılırken bağlanmaya çalışıp hata verebilir. Çözüm bir healthcheck tanımlayıp depends_on'u condition: service_healthy ile birlikte kullanmaktır:

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: appdb
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
      interval: 5s
      timeout: 3s
      retries: 5

  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    depends_on:
      db:
        condition: service_healthy

Artık web konteyneri, ancak pg_isready komutu başarılı döndükten sonra başlar. Bu, "veritabanı henüz hazır değil" hatalarının büyük kısmını ortadan kaldırır.

Günlük kullanım: temel komutlar

Yığını ayağa kaldırıp yönetmek için en sık kullanacağın komutlar şunlar:

  • docker compose up -d — tüm servisleri arka planda başlatır.
  • docker compose ps — çalışan servisleri ve durumlarını listeler.
  • docker compose logs -f web — belirli bir servisin günlüklerini canlı izler.
  • docker compose exec db psql -U app appdb — çalışan db konteyneri içinde komut çalıştırır.
  • docker compose down — servisleri durdurup kaldırır. Birimleri de silmek için down -v kullan.

Bir imajda değişiklik yaptıysan (örneğin kendi Dockerfile'ını kullanıyorsan) docker compose up -d --build ile yeniden derleyebilirsin.

Sık Sorulan Sorular

docker-compose ile docker compose arasındaki fark nedir?

docker-compose (tireli) Python ile yazılmış eski V1 aracıdır. docker compose (boşluklu) ise Docker CLI'a entegre edilmiş Go tabanlı V2 eklentisidir. Güncel kurulumlarda boşluklu sürümü kullanman önerilir; YAML söz dizimi büyük ölçüde aynıdır.

Verilerim konteyner silinince kaybolur mu?

Hayır — volumes ile tanımlanan adlandırılmış birimler konteyner yaşam döngüsünden bağımsızdır. docker compose down konteynerleri kaldırsa da birim kalır; veriler bir sonraki up komutunda yine oradadır. Yalnızca down -v birimleri de siler.

Compose üretim ortamı için uygun mu?

Tek sunuculu küçük ve orta ölçekli kurulumlar için gayet uygundur. Ancak çok düğümlü, otomatik ölçeklenen ve kendini onaran sistemler için Kubernetes gibi bir orkestratör daha doğru tercihtir. Compose'u geliştirme ve sade üretim senaryoları için, Kubernetes'i büyük ölçek için düşün.

Yığınını tek dosyada toplamak mı istiyorsun? Docker Compose ile geliştirme ve dağıtım ortamını sadeleştirmek için benimle iletişime geç — projenin altyapısını birlikte planlayalım.

Bu kategorideki tüm yazılar →

Devamı için