Bir açık kaynak projesinde “makinemde çalışıyor” genellikle teknik bir başarı değil, dokümantasyon ve ortam sözleşmesindeki boşluğun işaretidir. Yeni bir geliştiricinin depoyu klonladıktan sonra hangi sürümü kuracağını, hangi servisi başlatacağını, veritabanını nasıl hazırlayacağını ve hangi gizli değeri nereden alacağını tahmin etmesi gerekiyorsa proje henüz kolay kurulabilir değildir.
Docker Compose bu sorunu tek başına çözmez. Bir compose.yaml dosyası yalnızca birkaç konteyneri başlatabilir; fakat tekrarlanabilir bir geliştirme ortamı, bağımlılıkları, yapılandırmayı, veri ömrünü ve ilk çalıştırma akışını açık bir sözleşmeye dönüştürür. Başarı ölçütü şudur: Temiz bir makinede, belgelenmiş birkaç adımla uygulama kullanılabilir hâle geliyor mu?
Başlangıç deneyimini tasarlayın
Geliştirme ortamının ilk görevi çalışan bir uygulamayı tarif etmek değildir; sıfırdan başlayan kişiyi güvenli biçimde oraya götürmektir. İyi bir başlangıç akışı genellikle şu sırayı izler:
- Depoyu klonla ve örnek yapılandırmayı kopyala.
- Gerekli yerel değerleri açıkça doldur.
- Tek komutla bağımlılıkları ve uygulamayı başlat.
- Sağlık kontrolü veya kısa bir doğrulama komutuyla sistemin hazır olduğunu gör.
- Test verisi gerekiyorsa isteğe bağlı, tekrar çalıştırılabilir bir seed komutu kullan.
Bu akışta her manuel adım sorgulanmalıdır. Örneğin “önce PostgreSQL'i ayrıca kur” yerine veritabanını bir servis olarak tanımlamak daha tutarlıdır. “Bu SQL dosyasını bir kez elle çalıştır” yerine migration komutunu başlatma sürecine veya açık bir görev komutuna koymak daha güvenlidir.
Servis sınırlarını amaçlarına göre ayırın
Compose dosyasında her şeyi ayrı konteynere koymak zorunlu değildir. Uygulama, veritabanı, cache, kuyruk, nesne depolama veya e-posta test aracı gibi bağımlılıklar ayrı servisler olduğunda değer kazanır. Bu ayrım, bağımlılığın sürümünü, kalıcı verisini ve ağ erişimini görünür kılar.
Buna karşılık yalnızca tek bir süreçte çalışmak için bölünmüş servisler, geliştirme deneyimini zorlaştırabilir. Ölçüt teknik saflık değil, günlük iş akışıdır: Bir geliştirici API'yi değiştirirken bağımlılığı yeniden başlatmadan kodu yenileyebiliyor mu? Frontend, backend'in yerel adresini tutarlı biçimde bulabiliyor mu? Bir test, dış ağa ihtiyaç duymadan gerekli servislere erişebiliyor mu?
Servis adlarını altyapı ayrıntısından çok işlevi anlatacak şekilde seçmek de faydalıdır: api, web, db, cache, worker gibi adlar Compose ağında aynı zamanda anlaşılır DNS adları olur.
Yapılandırma ile gizli değerleri ayırın
Port, log seviyesi, etkin özellikler veya yerel URL gibi değerler ortam değişkenleriyle yapılandırılabilir. Ancak gerçek erişim anahtarları, parolalar veya üretim bağlantı dizeleri depoya girmemelidir. Bunun yerine .env.example dosyası her gerekli değişkeni açıklayan güvenli bir şablon sunmalıdır.
Örnek dosya boş bırakılmış bir liste değil, çalıştırılabilir bir başlangıç olmalıdır. Yerelde varsayılan olarak kullanılan servislerin örnek değerleri bulunabilir; kullanıcının kendi sağlayıcı hesabını gerektiren değerler ise açıkça işaretlenmelidir. Başlatma komutu eksik zorunlu değişken gördüğünde anlaşılır hata vermelidir.
Aynı değişkenin hem Compose dosyasında hem uygulama yapılandırmasında farklı adlarla geçmesi yaygın bir hata kaynağıdır. İsimleri ve sorumluluğu tek yerde belgelemek, “hangi portu hangi servis kullanıyor?” gibi küçük ama zaman alan sorunları azaltır.
Hazır olma durumunu başlangıç sırasından ayırın
Konteynerin başlatılmış olması, uygulamanın istek kabul etmeye hazır olduğu anlamına gelmez. Veritabanı işlemi çalışıyor olabilir ama bağlantı kabul etmiyor; migration henüz bitmemiş olabilir; bir worker kuyruğa bağlanamamış olabilir.
Bu nedenle yalnızca başlatma sırasına güvenmek yerine sağlık kontrolleri kullanmak gerekir. Veritabanı gerçekten sorgu kabul ediyor mu? API, migration sonrası sağlık endpoint'ine cevap veriyor mu? Bağımlı servisler mümkün olduğunda bu sağlıklı durumu beklemelidir. Bununla birlikte uygulamanın kendi yeniden deneme mantığı da bulunmalıdır; Compose sağlık kontrolü, geçici ağ kesintilerine karşı tek savunma olmamalıdır.
İlk kurulumda hata olursa logların okunabilir olması da önemlidir. “Connection refused” dışında hangi bağımlılığın beklenildiği, hangi bağlantı bilgisinin kullanıldığı ve sonraki güvenli adımın ne olduğu anlaşılmalıdır.
Veri ömrünü bilinçli yönetin
Geliştirici ortamında veritabanı ve dosya depolama verisinin her down komutunda silinmesi hem zaman kaybettirir hem de hatalı güvenlik algısı oluşturur. İsimli volume'lar, verinin konteyner yaşam döngüsünden ayrı kalmasını sağlar. Ancak bu kalıcılık açıkça belgelenmelidir: “temiz ortam” komutu neyi siler, seed verisi tekrar çalıştırılabilir mi, migration geri alınabilir mi?
Özellikle test ve geliştirme verisini gerçek kişisel verilerden ayırmak gerekir. Yerel örnek veri, üretim yedeğinden kopyalanmış bir dosya olmamalıdır. Anonimleştirilmiş veya sentetik kayıtlar; hem paylaşımı kolaylaştırır hem de demo ve test akışlarını güvenli kılar.
İsteğe bağlı bağımlılıkları profile alın
Her geliştiricinin aynı anda arama motoruna, mesaj kuyruğuna, nesne depolamaya veya e-posta yakalayıcıya ihtiyacı olmayabilir. Compose profilleri, temel ortamı hafif tutarken belirli özellikler için ek servis başlatmayı mümkün kılar.
Örneğin varsayılan komut api, web ve db ile başlayabilir; entegrasyon testleri için queue ve mail profili eklenebilir. Bu ayrım belgelerde de görünmelidir. Bir özelliğin çalışması belirli profile bağlıysa, arayüzde belirsiz hata vermek yerine kurulum yönergesi sunmak daha iyi deneyim sağlar.
Belgeleri komutlarla doğrulayın
README'deki her kurulum komutu düzenli olarak gerçek ortamda çalıştırılmalıdır. En iyi test, temiz bir volume ve yeni klonlanmış depo ile “quick start” adımlarını bir kişinin izlemesidir. Bu kontrol, eksik .env değişkenlerini, unutulmuş migration'ları ve dışarıya bağımlı gizli varsayımları ortaya çıkarır.
Compose dosyası geliştirme ortamının tamamı değildir; fakat iyi tasarlanmışsa projenin ilk katkı eşiğini ciddi biçimde düşürür. Açık servis sınırları, güvenli yapılandırma, sağlık kontrolleri, bilinçli veri ömrü ve doğrulanmış belgeler birlikte çalıştığında “çalışıyor” ifadesi kişisel bir durum olmaktan çıkar, tekrar üretilebilir bir vaat hâline gelir.