Merhaba arkadaşlar, bugün sizlere Docker Compose ile uğraşan herkesin mutlaka hakim olması gereken, docker-compose.yml dosyasının temel yapısını ve en önemli bölümlerini anlatacağım. Bu rehberi okuduktan sonra, karşınıza çıkan her compose dosyasını rahatlıkla okuyabilir, kendi ihtiyaçlarınıza göre düzenleyebilir ve birden fazla konteyneri tek komutla yönetmenin keyfini çıkarabilirsiniz. Ben de kendi sunucu ortamlarımda bu yapıyı sıklıkla kullanıyorum.
Docker Compose Nedir ve Neden Önemli?
Docker Compose, tek bir komutla (docker-compose up) birden fazla Docker konteynerini tanımlamamıza, başlatmamıza ve birbirine bağlamamıza yarayan bir araçtır. Özellikle web uygulamaları (örn: bir web sunucusu, bir veritabanı ve bir önbellek sunucusu) gibi birbiriyle konuşan servisleri yönetmek için vazgeçilmezdir. Tüm bu ilişki, tek bir YAML dosyasında tanımlanır.
Temel Yapı Taşları: version, services, networks, volumes
Temel bir docker-compose.yml dosyası genellikle bu dört ana bölümden oluşur. Şimdi bunları teker teker inceleyelim.
version Bölümü
Bu bölüm, kullandığımız Compose dosya formatının sürümünü belirtir. Farklı sürümler, farklı özellikleri ve yazım kurallarını destekler. En yaygın ve stabil kullanılan sürüm "3.8"dir. Bu satır, Docker Engine ve Compose sürümünüzle uyumlu olmalıdır.
services Bölümü (En Önemlisi!)
Bu, compose dosyamızın kalbidir. Çalıştırmak istediğimiz her bir konteyner (servis) burada tanımlanır. Her servis için image, port, environment variables, volumes gibi ayarları yaparız.
Örnek bir "web" ve "db" servisi tanımlayalım:
Burada, `web` servisi 80 portunu host makinenin 80 portuna bağlar ve bir klasörü mount eder. `depends_on` ile de `db` servisi başladıktan sonra kendisinin başlayacağını söyler. `db` servisi ise ortam değişkenleri ve kalıcı bir volume ile tanımlanmış.
volumes Bölümü
Servislerin dışında, üst seviyede volume'leri tanımladığımız bölümdür. Yukarıdaki örnekte `db_data` isimli bir volume kullandık. İşte onun tanımı burada yapılır. Docker, bu volume'ü otomatik olarak yaratır ve yönetir. Bu sayede konteyner silinse bile veriler korunur.
Eğer host makinenizdeki belirli bir yolu mount etmek istiyorsanız (buna "bind mount" denir), bunu direkt `services` altında, yukarıda `./web-data` yolunda yaptığımız gibi belirtirsiniz. Bu durumda bu bölüme ek bir tanım gerekmez.
networks Bölümü
Varsayılan olarak Compose, tüm servisleri aynı özel ağa bağlar. Ancak özel ağ ayarları yapmak veya harici ağlar kullanmak isterseniz bu bölümü kullanırsınız. Örneğin, özel bir subnet ile bir ağ tanımlayabilirsiniz.
Servislerinizi bu ağa bağlamak için, servis tanımına `networks: - benim_agim` satırını eklemeniz gerekir.
Dikkat Edilmesi Gerekenler ve Pratik İpuçları
- YAML dosyalarında girinti (indent) çok önemlidir. Boşluk sayılarına dikkat edin. Genellikle 2 boşluk kullanılır.
- `container_name` belirtmezseniz, Docker Compose proje ismi ve servis isminden otomatik bir isim üretir. Ben genelde belirlemeyi tercih ediyorum, logları takip etmek daha kolay oluyor.
- Ortam değişkenlerini (environment) direkt dosyada yazmak güvenlik riski olabilir. Hassas bilgiler için .env dosyası kullanmanızı veya Docker'ın kendi secret yönetimini öğrenmenizi şiddetle tavsiye ederim.
- Dosya yolunu belirtirken, ./ ile başlayan göreli yollar, docker-compose.yml dosyasının bulunduğu dizine göredir. Çok dikkat etmelisiniz.
- Her değişiklikten sonra
komutunu çalıştırmak yerine,
ve sonra tekrar
yapmak bazen daha temiz sonuçlar verir, özellikle network veya volume tanımlarını değiştirdiyseniz.
Sonuç
Gördüğünüz gibi, Docker Compose dosyasının temel yapısı aslında oldukça mantıklı ve modüler. `version` ile başlayıp, `services` ile konteynerlerimizi tanımlıyor, `volumes` ve `networks` ile de bu konteynerlerin kaynaklarını ve iletişim yollarını yönetiyoruz.
Artık karşınıza çıkan bir compose dosyasını daha rahat analiz edebilirsiniz. Peki siz bu yapıyı kendi sunucularınızda nasıl kullanıyorsunuz? Özellikle `networks` kısmında özel ayarlar yapıyor musunuz yoksa varsayılan ağ yeterli mi geliyor? Aklınıza takılan veya eklemek istediğiniz bir nokta varsa aşağıya yazmaktan çekinmeyin. Hep birlikte öğrenelim.
Docker Compose, tek bir komutla (docker-compose up) birden fazla Docker konteynerini tanımlamamıza, başlatmamıza ve birbirine bağlamamıza yarayan bir araçtır. Özellikle web uygulamaları (örn: bir web sunucusu, bir veritabanı ve bir önbellek sunucusu) gibi birbiriyle konuşan servisleri yönetmek için vazgeçilmezdir. Tüm bu ilişki, tek bir YAML dosyasında tanımlanır.
Temel bir docker-compose.yml dosyası genellikle bu dört ana bölümden oluşur. Şimdi bunları teker teker inceleyelim.
Bu bölüm, kullandığımız Compose dosya formatının sürümünü belirtir. Farklı sürümler, farklı özellikleri ve yazım kurallarını destekler. En yaygın ve stabil kullanılan sürüm "3.8"dir. Bu satır, Docker Engine ve Compose sürümünüzle uyumlu olmalıdır.
YAML:
version: '3.8'
Bu, compose dosyamızın kalbidir. Çalıştırmak istediğimiz her bir konteyner (servis) burada tanımlanır. Her servis için image, port, environment variables, volumes gibi ayarları yaparız.
Örnek bir "web" ve "db" servisi tanımlayalım:
YAML:
services:
web:
image: nginx:latest
container_name: benim_nginx
ports:
- "80:80"
volumes:
- ./web-data:/usr/share/nginx/html
depends_on:
- db
db:
image: mysql:8.0
container_name: benim_mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: cok_gizli_sifrem
MYSQL_DATABASE: benimdb
volumes:
- db_data:/var/lib/mysql
Burada, `web` servisi 80 portunu host makinenin 80 portuna bağlar ve bir klasörü mount eder. `depends_on` ile de `db` servisi başladıktan sonra kendisinin başlayacağını söyler. `db` servisi ise ortam değişkenleri ve kalıcı bir volume ile tanımlanmış.
Servislerin dışında, üst seviyede volume'leri tanımladığımız bölümdür. Yukarıdaki örnekte `db_data` isimli bir volume kullandık. İşte onun tanımı burada yapılır. Docker, bu volume'ü otomatik olarak yaratır ve yönetir. Bu sayede konteyner silinse bile veriler korunur.
YAML:
volumes:
db_data:
Eğer host makinenizdeki belirli bir yolu mount etmek istiyorsanız (buna "bind mount" denir), bunu direkt `services` altında, yukarıda `./web-data` yolunda yaptığımız gibi belirtirsiniz. Bu durumda bu bölüme ek bir tanım gerekmez.
Varsayılan olarak Compose, tüm servisleri aynı özel ağa bağlar. Ancak özel ağ ayarları yapmak veya harici ağlar kullanmak isterseniz bu bölümü kullanırsınız. Örneğin, özel bir subnet ile bir ağ tanımlayabilirsiniz.
YAML:
networks:
benim_agim:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
Servislerinizi bu ağa bağlamak için, servis tanımına `networks: - benim_agim` satırını eklemeniz gerekir.
- YAML dosyalarında girinti (indent) çok önemlidir. Boşluk sayılarına dikkat edin. Genellikle 2 boşluk kullanılır.
- `container_name` belirtmezseniz, Docker Compose proje ismi ve servis isminden otomatik bir isim üretir. Ben genelde belirlemeyi tercih ediyorum, logları takip etmek daha kolay oluyor.
- Ortam değişkenlerini (environment) direkt dosyada yazmak güvenlik riski olabilir. Hassas bilgiler için .env dosyası kullanmanızı veya Docker'ın kendi secret yönetimini öğrenmenizi şiddetle tavsiye ederim.
- Dosya yolunu belirtirken, ./ ile başlayan göreli yollar, docker-compose.yml dosyasının bulunduğu dizine göredir. Çok dikkat etmelisiniz.
- Her değişiklikten sonra
Bash:
docker-compose up -d
Bash:
docker-compose down
Bash:
docker-compose up -d
Gördüğünüz gibi, Docker Compose dosyasının temel yapısı aslında oldukça mantıklı ve modüler. `version` ile başlayıp, `services` ile konteynerlerimizi tanımlıyor, `volumes` ve `networks` ile de bu konteynerlerin kaynaklarını ve iletişim yollarını yönetiyoruz.
Artık karşınıza çıkan bir compose dosyasını daha rahat analiz edebilirsiniz. Peki siz bu yapıyı kendi sunucularınızda nasıl kullanıyorsunuz? Özellikle `networks` kısmında özel ayarlar yapıyor musunuz yoksa varsayılan ağ yeterli mi geliyor? Aklınıza takılan veya eklemek istediğiniz bir nokta varsa aşağıya yazmaktan çekinmeyin. Hep birlikte öğrenelim.