Konteyner, hafif bir sanal makine değildir. İçinde ayrı bir işletim sistemi çalışmaz. Gerçekte olan şey daha basittir: ana makinenin çekirdeğinde çalışan sıradan bir süreç, yalnızca ne göreceği kısıtlanmış hâlde.
Yalıtım nereden geliyor
İki çekirdek özelliği bu illüzyonu üretir.
Ad alanları (namespaces) sürecin ne görebileceğini sınırlar. Ayrı bir süreç ad alanı, konteyner içindeki uygulamanın yalnızca kendi süreçlerini görmesini sağlar — ana makinedekileri göremez. Ayrı bir ağ ad alanı ona kendi arayüzlerini ve IP’sini verir. Ayrı bir bağlama ad alanı kendi dosya sistemi görünümünü verir.
Kaynak grupları (cgroups) ise ne kadar kullanabileceğini sınırlar: işlemci payı, bellek tavanı, disk ve ağ bant genişliği.
Kısacası ad alanları görünürlüğü, kaynak grupları tüketimi kısıtlar. Konteyner bu ikisinin birleşiminden ibarettir; sihir yoktur.
Bu yüzden konteyner içindeki süreç ana makinede ps ile görülebilir — orada sıradan bir süreçtir.
Çekirdek paylaşılır
En önemli sonuç budur: tüm konteynerler ana makinenin çekirdeğini kullanır.
Bunun iki etkisi vardır. Birincisi hafiflik — ayrı bir çekirdek yüklenmediği için başlangıç milisaniyeler sürer ve bellek yükü küçüktür.
İkincisi güvenlik sınırıdır. Çekirdek ortak olduğu için konteyner sınırı, sanal makine sınırından daha incedir. Çekirdekteki bir açık, konteynerden çıkmanın yolu olabilir.
Pratik sonuç: birbirine güvenmeyen iş yükleri aynı çekirdeği paylaşmamalıdır. Karşılaştırmanın tamamı sanal makine mi konteyner mi yazısında.
Ayrıca Linux konteynerleri Linux çekirdeği gerektirir; başka işletim sistemlerinde arka planda bir sanal makine çalışır.
İmaj ve konteyner farkı
İmaj salt okunur bir şablondur: uygulama, bağımlılıkları ve dosya sistemi içeriği. Diskte durur, çalışmaz.
Konteyner, o imajdan üretilmiş çalışan bir örnektir. Aynı imajdan yüzlerce konteyner başlatılabilir.
İlişki, kurulum dosyası ile çalışan program arasındaki ilişkiye benzer. İmaj değişmez; konteyner geçicidir.
Katmanlar
İmajlar tek bir blok değildir; üst üste binen katmanlardan oluşur. Her yapı adımı yeni bir katman üretir.
İki kazanç sağlar. Katmanlar paylaşılır: aynı temel imajı kullanan on farklı uygulama, o katmanı diskte bir kez tutar. Ve değişmeyen katmanlar yeniden oluşturulmaz — yalnızca değişen adımdan sonrası yeniden hesaplanır.
Bu, imaj yazarken sıralamayı önemli kılar: az değişen şeyler (bağımlılık kurulumu) üste, sık değişen şeyler (uygulama kodu) alta konur. Ters sıralanmış bir imajda her küçük kod değişikliği tüm bağımlılıkları yeniden indirir.
Sıralama ve diğer tipik hatalar için Dockerfile denetleyici aracı var.
Yazma katmanı ve geçicilik
Çalışan konteyner, salt okunur katmanların üzerine ince bir yazma katmanı ekler. Konteyner içinde yapılan her değişiklik oraya gider.
Konteyner silindiğinde o katman da silinir. Bu bir kusur değil, tasarımın kendisidir: her konteyner aynı imajdan doğar ve öngörülebilir davranır.
Kalıcı veri için dışarıdan birim bağlanır. Veritabanı verisi, yüklenen dosyalar ve günlükler konteynerin içinde tutulmaz.
Aynı nedenle konteyner içinde elle yapılan düzeltmeler kalıcı değildir. Değişiklik imaja girmelidir; aksi hâlde bir sonraki yeniden başlatmada kaybolur.
Kayıt defteri ve etiketler
İmajlar bir kayıt defterinde saklanır ve etiketle adlandırılır.
Etiketler taşınabilir — latest bugün başka, yarın başka bir imaja işaret edebilir. Bu yüzden üretimde sabit sürüm, kritik yerlerde ise değişmez özet kullanılır.
latest ile IfNotPresent çekme ilkesinin birlikte kullanılması ayrı bir tuzaktır: düğüm eski kopyayı kullanır ve yeni sürüm hiç indirilmez. “Dağıttım ama eski kod çalışıyor” durumunun klasik nedeni budur.
Compose dosyalarında bu ve benzeri sorunları taramak için Compose denetleyici aracı var.
Kök olarak çalışmak
Öntanımlı olarak konteyner içindeki süreç kök kullanıcıdır. Ad alanları bunu ana makineden yalıtır, ama yine de gereksiz bir risktir — özellikle bir birim bağlıysa, oraya kök sahipliğinde dosyalar yazar.
İyi imajlar kendi kullanıcısını tanımlar. Ayrıcalıklı kip, ana makine ağı ve Docker soketinin bağlanması ise yalıtımı büyük ölçüde ortadan kaldırır ve gerçekten gerekmedikçe kullanılmamalıdır.
Kısaca
Konteyner, ad alanlarıyla görünürlüğü ve kaynak gruplarıyla tüketimi kısıtlanmış sıradan bir süreçtir. İmaj değişmez şablon, konteyner onun çalışan örneğidir.
Üç ilke pratikte her şeyi belirler: çekirdek paylaşılır, konteyner geçicidir, kalıcı veri dışarıda durur. Bu üçü kavrandığında geri kalanı araç kullanımıdır.
Kümede nasıl çalıştırıldıkları Kubernetes nedir yazısında.