Docker Compose ile çok servisli uygulama kurmak: dosya yapısı ve başlatma sırası
Docker Compose ile web ve veritabanı servislerini tek dosyada tanımlayın: compose.yaml yapısı, depends_on ve healthcheck, volume, ortam değişkenleri, komutlar.
Compose neden gerekir?
Gerçek bir uygulama nadiren tek konteynerden oluşur: bir web servisi, bir veritabanı, belki bir önbellek ve bir arka plan işçisi. Bunları tek tek docker run komutlarıyla başlatmak, ağları, volume'leri ve ortam değişkenlerini her seferinde elle yazmak anlamına gelir. Komutlar uzar, sırayı unutursunuz, ekipteki herkesin aynı şekilde çalıştırdığından emin olamazsınız.
Docker Compose, uygulamanın bütün servislerini tek bir YAML dosyasında tanımlamanıza izin verir. Aynı dosya, tek komutla bütün yığını ayağa kaldırır ve tek komutla kaldırır. Bu dosya depoya girer, böylece yeni bir ekip arkadaşı projeyi klonladığı gün uygulamayı çalışır halde görür.
Docker belgeleri Compose uygulama modelini şu ana öğeler etrafında anlatır: servisler (uygulamanın hesaplama bileşenleri), ağlar (servisler arası iletişim) ve volume'ler (kalıcı veri). Gizli bilgiler ve yapılandırma dosyaları için ayrıca secrets ve configs öğeleri de vardır.
Adım adım: ilk Compose dosyası
Dosya adı olarak güncel belgeler compose.yaml kullanır; eski docker-compose.yml adı da tanınır. Bir web servisi ve bir veritabanından oluşan örnek:
services: web: build: . ports: - "<ana-makine-portu>:<konteyner-portu>" environment: DATABASE_HOST: db depends_on: db: condition: service_healthy restart: unless-stopped db: image: postgres:<sürüm> volumes: - db-veri:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
volumes: db-veri:
Bu dosyada servis, volume ve sağlık kontrolü birlikte çalışır. web servisi kendi Dockerfile'ından derlenir (build) ve bir port yayınlar. db servisi hazır bir imajdan gelir ve verisini adlandırılmış bir volume'de tutar. En altta volume'ler tanımlanır.
Dikkat edilecek ayrıntı: web servisi veritabanına "db" adıyla ulaşır. Compose, projedeki servisleri varsayılan olarak ortak bir ağa koyar ve servis adını DNS adı olarak kullanılabilir hale getirir; ayrıca ağ tanımlamanız gerekmez.
Port değeri için belgeler tırnak kullanmayı önerir. YAML bazı sayı biçimlerini farklı yorumlayabilir; tırnak bu belirsizliği önler.
Başlatma sırası: depends_on ve healthcheck
En sık düşülen hata, depends_on yazıldığı için veritabanının hazır olduğunu varsaymaktır. Docker belgelerine göre depends_on, konteynerlerin bağımlılık sırasına göre oluşturulmasını ve başlatılmasını sağlar ama varsayılan davranışta yalnızca konteynerin çalıştığını bekler, uygulamanın hazır olduğunu değil. Veritabanı süreci başlamış ama bağlantı kabul etmiyorsa, web servisi ilk açılışta hata verir.
Çözüm, bağımlı servisin sağlık kontrolü (healthcheck) tanımlamak ve depends_on'da condition: service_healthy kullanmaktır. Bu durumda Compose, bağımlılığın sağlık kontrolü geçene kadar bekler. Yukarıdaki örnekte db servisinin sağlık kontrolü veritabanının bağlantı kabul edip etmediğine bakar.
test alanı bir liste olarak yazılır ve ilk öğe CMD, CMD-SHELL ya da NONE olabilir. Tek bir metin yazarsanız bu, CMD-SHELL ile aynı kabul edilir. Sağlık kontrolü yoksa service_healthy beklenen bir şey ifade etmez; önce kontrolü tanımlayın.
Uygulama tarafında da bağlantı yeniden deneme mantığı iyi bir sigortadır: veritabanı sonradan yeniden başlatılırsa, uygulama kendini toparlayabilmelidir.
Ortam değişkenleri, volume ve ağ ayarları
Ortam değişkenleri farklı yollardan verilir. environment altında doğrudan yazarsınız ya da env_file ile bir dosyadan okutursunuz. Belgelere göre bunlar birlikte kullanıldığında environment değerleri env_file değerlerini ezer; birden fazla dosyada aynı değişken varsa listedeki sonuncu geçerlidir. Parola gibi değerleri Compose dosyasına yazmak yerine depoya girmeyen bir .env dosyasından okutun.
Volume'ler farklı biçimlerde bağlanır: adlandırılmış volume (veri için) ve ana makine klasörü (geliştirme sırasında kod ve yapılandırma için). Kısa söz dizimi VOLUME:KONTEYNER_YOLU[:ERİŞİM_MODU] biçimindedir; ro eklemek salt okunur yapar. Kısa sözdiziminde olmayan bir ana makine klasörü kendiliğinden oluşturulur; bunu istemiyorsanız uzun söz dizimiyle create_host_path: false verirsiniz.
Ağlar için çoğu proje varsayılan ağla yetinir. Servisleri ayırmak istediğinizde (örneğin yalnızca web servisinin dış dünyaya bakması) birden fazla ağ tanımlar ve servisleri ilgili ağlara bağlarsınız. Böylece veritabanı yalnızca arka uç ağında olur ve ön yüz servisi ona hiç ulaşamaz.
Günlük komutlar
Compose'un günlük işi birkaç komutla yürür:
docker compose up -d docker compose ps docker compose logs docker compose down
up, tanımlı bütün servisleri başlatır; -d arka planda çalıştırır. ps servislerin durumunu listeler, logs konteyner çıktılarını gösterir. down servisleri durdurup kaldırır; volume'ler varsayılan olarak korunur, böylece veri kaybolmaz.
Kod değiştikten sonra imajı yeniden derlemek için up komutuna derleme bayrağı eklenir. Tek bir servisin günlüğünü izlemek için logs komutuna servis adı verilir. Bir sorunda sırayla bakılacaklar: ps ile hangi servis kalktı, logs ile neden düştü, healthcheck durumu ne.
Birden fazla ortam için temel dosyayı ortak tutup farklılıkları ek dosyalarla birleştirmek yaygın bir kalıptır. Örneğin geliştirmede bind mount ve açık portlar, üretimde ise yeniden başlatma politikası ve kaynak sınırları ek dosyada yer alır.
Sık yapılan hatalar ve kontrol listesi
- Servise localhost ile bağlanmak: Konteyner içindeki localhost, o konteynerin kendisidir. Servis adı kullanın.
- depends_on ile hazır olma varsaymak: Sağlık kontrolü ve yeniden deneme ekleyin.
- Gizli bilgiyi dosyaya yazıp depoya göndermek: .env dosyasını depo dışında tutun, örnek bir şablon dosyası paylaşın.
- down ile volume silmek: Volume'leri de silen seçenek veritabanı verisini yok eder. Alışkanlıkla kullanmayın.
- Her servisin portunu yayınlamak: Yalnızca dışarıya açılması gerekeni yayınlayın.
- Port değerini tırnaksız yazmak: Beklenmeyen YAML yorumlarına yol açar.
- Tek dosyaya her ortamı sığdırmak: Geliştirme ve üretim ayarlarını ayırın.
Yayından önce: Temiz bir makinede klonlayıp tek komutla çalışıyor mu? Veriler down sonrası up ile geri geliyor mu? Bir servis kasıtlı olarak durdurulunca diğerleri nasıl davranıyor?
Mindset programlarında nerede çalışılır?
Temel Docker Eğitimi'nin müfredatında "Docker Compose ile Çoklu Servis Yönetimi" ve "Docker ve CI/CD Entegrasyonu" başlıkları vardır; çok servisli bir uygulamayı geliştirme ortamında ayağa kaldırmak isteyen geliştiriciler ve DevOps'a yeni başlayanlar için uygundur. Docker ve Container Teknolojileri eğitimi ise "Docker Compose ile Çok Konteynerli Uygulamalar" modülünü üretim odaklı başlıklarla (registry, imaj güvenliği, üretim ortamı) birlikte işler.
Ekip içinde Compose dosyasını ortak bir standart haline getirmek, yeni gelenlerin kurulum süresini azaltır ve "makinemde çalışıyor" tartışmalarını kısaltır.
İlgili Mindset programı
Temel Docker Eğitimi
Sık sorulan sorular
Compose dosyasında servisler birbirine nasıl erişir?
Compose uygulama için ortak bir ağ oluşturur ve servisler birbirine servis adıyla erişir. Bu yüzden web servisinin veritabanı adresi olarak localhost değil, dosyadaki veritabanı servisinin adı yazılır. Yayımlanan port yalnızca konteynerin dışından, örneğin tarayıcıdan erişim içindir; servisler arası trafik için gerekmez.
docker-compose ile docker compose komutu aynı mı?
Eski sürümde ayrı bir docker-compose programı kullanılırdı. Güncel belgeler Docker komutunun bir eklentisi olarak docker compose biçimini kullanır. Dosya formatı ve işlev aynıdır; yeni kurulumlarda boşluklu biçimi tercih edin. Eski betiklerde tireli komut görürseniz, çalıştığı ortamda hangisinin kurulu olduğunu kontrol edip komutu güncelleyin.
Compose dosyasında ortam değişkenlerini nasıl güvenli tutarım?
Parola ve anahtarları doğrudan dosyaya yazmayın. Depoya girmeyen bir .env dosyasından okutun ya da Compose'un secrets özelliğini kullanın. Depoda yalnızca değerleri boş bırakılmış örnek bir şablon dosya bulundurmak, ekip arkadaşlarına neyin gerektiğini söyler.
down komutu verilerimi siler mi?
Varsayılan olarak hayır. down konteynerleri ve ağları kaldırır ama adlandırılmış volume'leri korur, bu yüzden veritabanı verisi sonraki up ile geri gelir. Volume'leri de silen seçenek ayrıca verilmedikçe veri silinmez; o seçeneği bilinçli kullanın.
Compose üretimde kullanılabilir mi?
Tek sunuculu, küçük ve orta ölçekli uygulamalar için kullanılabilir; yeniden başlatma politikası, kaynak sınırları ve günlük ayarları eklenmelidir. Çok sunuculu ölçekleme, otomatik kendini onarma gibi ihtiyaçlar varsa bir orkestrasyon platformu daha uygun olur.