71 puan yazan GN⁺ 2026-01-21 | 9 yorum | WhatsApp'ta paylaş
  • docker run ubuntu çalıştırdığınızda host Linux çekirdeğini paylaşır ve Ubuntu yalnızca kullanıcı alanı araçlarını sağlar
  • uname -r çıktısı host çekirdek sürümünü gösterir, yalnızca /etc/os-release Ubuntu bilgisi olarak görünür
  • VM'lerin her birinin kendine ait bir çekirdeği vardır ve açılışları dakikalar sürebilir; konteynerler ise milisaniyeler içinde başlar ve donanım sanallaştırması olmadan işletim sistemi düzeyinde yalıtım ile host çekirdeğini paylaşarak düşük ek yük sağlar
  • Linux'taki sistem çağrısı ABI kararlılığı sayesinde farklı dağıtım konteynerleri aynı çekirdek üzerinde çalışabilir
  • 16 GB RAM ortamında hafif konteynerler için 50-100, orta ölçekliler için 10-30, büyük konteynerler için ise 5-10 adet pratik sınır kabul edilir
  • Bu mimariyi anlamak önemlidir; çünkü çekirdek açıkları tüm konteynerleri etkiler ve temel imaj seçimi uyumluluk ile güvenliği doğrudan etkiler

“Ubuntu çalıştırmak” ne anlama geliyor

  • docker run ubuntu:22.04 çalıştırdığınızda Ubuntu gibi görünen bir bash istemi elde edersiniz ve apt update ile paket kurulumu yapabilirsiniz
  • Ancak konteyner içinde uname -r çalıştırdığınızda host çekirdek sürümü (ör. 6.5.0-44-generic) gösterilir
  • /etc/os-release dosyası Ubuntu 22.04 olarak görünür, ancak çekirdek host makineye aittir ve “Ubuntu” kısmı yalnızca kullanıcı alanını oluşturan dosya sisteminden ibarettir

Konteyner vs sanal makine: mimari karşılaştırma

  • VM'ler donanımı sanallaştırır, konteynerler ise işletim sistemini sanallaştırır
  • Başlıca farklar:
    • Çekirdek: VM'lerin her birinin ayrı çekirdeği vardır, konteynerler host çekirdeğini paylaşır
    • Açılış süresi: VM'ler dakikalar, konteynerler milisaniyeler
    • Bellek ek yükü: VM'ler 512MB-4GB, konteynerler 1-10MB
    • Disk kullanımı: VM'ler 10-100GB, konteyner imajları 10-500MB
    • Yalıtım seviyesi: VM'ler donanım düzeyinde, konteynerler süreç düzeyinde
    • Performans: VM'lerde yaklaşık %5-10 ek yük vardır, konteynerler ise yerel performansa yakın çalışır

Temel imajın gerçekte içerdiği bileşenler

  • ubuntu:22.04 çekildiğinde indirilen tarball'ın içeriği:
  • 1. Gerekli ikili dosyalar (/bin, /usr/bin)

    • /bin/bash (kabuk), /bin/ls (dosya listesi), /bin/cat (dosya gösterimi)
    • /usr/bin/apt (paket yöneticisi), /usr/bin/dpkg (Debian paket aracı)
  • 2. Paylaşılan kütüphaneler (/lib, /usr/lib)

    • glibc ve diğer programların bağlandığı paylaşılan kütüphaneler
    • /lib/x86_64-linux-gnu/libc.so.6 (C kütüphanesi - tüm C programlarının temeli)
    • libpthread.so.0, libm.so.6 gibi temel kütüphaneler
  • 3. Yapılandırma dosyaları (/etc)

    • /etc/apt/sources.list (paket depoları)
    • /etc/passwd (kullanıcı veritabanı)
    • /etc/resolv.conf (DNS ayarı, genelde hosttan bağlanır)
  • 4. Paket veritabanı

    • /var/lib/dpkg/status (kurulu paketler)
    • /var/lib/apt/lists/ (kullanılabilir paket önbelleği)
  • Çekirdek, bootloader ve sürücüler dahil değildir

Çekirdek aynı kalır, her şey değişir

  • Linux çekirdeğinin sunduğu işlevler: süreç zamanlama, bellek yönetimi, dosya sistemi işlemleri, ağ yığını, aygıt sürücüleri, sistem çağrıları
  • Bir konteyner süreci open(), read(), fork() çağırdığında bunlar doğrudan host çekirdeğine iletilir
  • Çekirdek, ilgili sürecin “Ubuntu konteyneri” mi yoksa “Alpine konteyneri” mi olduğunu ne bilir ne de önemser
  • Sistem çağrısı arayüzünün kararlılığı

    • Linux syscall ABI'si son derece kararlıdır
    • glibc 2.31 (Ubuntu 20.04) ile derlenmiş bir ikilinin Ubuntu 24.04 çekirdeğinde de çalışabilmesinin nedeni:
      • çekirdeğin geriye dönük uyumluluğu koruması
      • sistem çağrısı numaralarının değişmemesi
      • yeni özellikler eklenirken eskilerin neredeyse hiç kaldırılmaması
    • Bu yüzden çekirdek 6.5 çalıştıran bir host üzerinde Ubuntu 18.04 konteyneri de çalıştırılabilir

Uygulamalı olarak deneyin: aynı çekirdek, farklı kullanıcı alanı

  • Farklı temel imajlarda aynı çekirdek sorgusunu çalıştırdığınızda tüm imajların aynı host çekirdeğini paylaştığını görebilirsiniz
  • ubuntu:22.04, debian:12, alpine:3.19, fedora:39, archlinux:latest için çekirdek sürümü aynıdır (6.5.0-44-generic)
  • Konteynerler arasındaki fark uname ikilisi ve libc gibi userland bileşenleridir

Konteynerler neden bu kadar verimlidir

  • 1. Çekirdek tekrarı yok

    • VM'lerin her biri tüm çekirdeği belleğe yükler (yaklaşık 100-500MB)
    • 10 VM, bellekte 10 çekirdek tüketirken 10 konteyner yalnızca tek bir çekirdek kullanır
  • 2. Anında başlangıç

    • VM açılış sırası: BIOS → bootloader → çekirdek → init sistemi → servisler
    • Konteynerler yalnızca fork() ve exec() çağrılarıyla milisaniyeler içinde süreç haline gelir
    • Tipik VM açılışı: 30-60 saniye / konteyner başlangıcı: yaklaşık 0.347 saniye
  • 3. Paylaşılan imaj katmanları

    • ubuntu:22.04 ile 100 konteyner çalıştırıldığında temel imaj katmanı diskte yalnızca bir kez bulunur
    • Her konteyner sadece değişiklikler için ince bir copy-on-write katmanı alır
  • 4. Çekirdek üzerinden bellek paylaşımı

    • Çekirdeğin page cache'i paylaşılır
    • 50 konteyner aynı dosyayı okursa çekirdek onu yalnızca bir kez önbelleğe alır
    • Aynı paylaşılan kütüphaneler kullanıldığında copy-on-write ile bellek sayfaları paylaşılabilir

Konteyner çalıştırma sınırının hesabı

  • Bellek analizi (16GB RAM'li VM baz alınarak)

    • Toplam RAM: 16,384 MB
    • Host OS ek yükü: -1,024 MB
    • Docker daemon: -256 MB
    • Konteyner runtime ek yükü: -512 MB
    • Konteynerler için kullanılabilir alan: 14,592 MB
  • Konteyner türlerine göre bellek kullanımı

    • En düşük (sleep): yaklaşık 1MB
    • Alpine + küçük uygulama: yaklaşık 25MB
    • Ubuntu + Python uygulaması: yaklaşık 120MB
    • Ubuntu + Java uygulaması: yaklaşık 500MB
    • Node.js servisi: yaklaşık 200MB
  • Teorik azami değer

    • En küçük konteyner (1MB): 14,592 adet
    • Alpine + küçük uygulama (25MB): 583 adet
    • Ubuntu + Python (120MB): 121 adet
    • Java mikroservisi (500MB): 29 adet
  • Gerçek sınır

    • Bellek dışında dikkate alınması gerekenler:
      • CPU zamanlama: çok fazla konteyner rekabete girerse gecikme sıçramaları yaşanabilir
      • Dosya tanımlayıcıları: varsayılan ulimit 1024
      • Ağ portları: port eşlemesinde yalnızca 65,535 adet kullanılabilir
      • PID'ler: /proc/sys/kernel/pid_max sınırı (varsayılan: 32,768)
      • Disk I/O: OverlayFS ek yükü, çok sayıda katmanın taranması gerekir
    • 16GB'lık bir VM'de gerçek iş yükleri çalıştırıldığında pratik sınırlar:
      • Hafif konteynerler (API, worker): 50-100 adet
      • Orta ölçekli konteynerler (DB, cache): 10-30 adet
      • Büyük konteynerler (ML model, JVM uygulaması): 5-10 adet

Linux dağıtımları arası uyumluluk

  • Çekirdek ABI taahhüdü

    • Linux, kararlı bir syscall arayüzünü korur
    • Eski çekirdekler için derlenmiş ikililer yeni çekirdeklerde de çalışır
    • Ubuntu 18.04 ikilisi çekirdek 6.5 üzerinde sorunsuz çalışır
  • Uyumluluğun bozulduğu durumlar

    • Çekirdek özelliği gereksinimleri: konteyner, çekirdekte olmayan bir özelliğe ihtiyaç duyarsa (ör. io_uring için çekirdek 5.1+ gerekir)
    • Çekirdek modülü bağımlılıkları: Wireguard için wireguard çekirdek modülü gerekir, NVIDIA konteynerleri için nvidia çekirdek sürücüsü gerekir
    • Seccomp/capability kısıtlamaları: host, konteynerin ihtiyaç duyduğu syscall'ları engelliyorsa (ör. ptrace kullanımı için --cap-add SYS_PTRACE gerekir)

Temel imaj seçme rehberi

Temel imaj Boyut Paket yöneticisi Kullanım alanı
scratch 0 MB Yok statik derlenmiş Go/Rust ikilileri
alpine 7 MB apk minimal konteynerler, musl libc
distroless 20 MB Yok güvenlik odaklı, kabuk ve paket yöneticisi yok
debian-slim 80 MB apt boyut ve uyumluluk dengesi
ubuntu 78 MB apt geliştirme kolaylığı
fedora 180 MB dnf güncel paketler, SELinux
  • Hangi imaj ne zaman kullanılmalı

    • scratch: statik derlenmiş ikililer için, işletim sistemi olmadan yalnızca ikiliyi içerir
    • alpine: kabuk erişimi gereken minimal imaj; glibc yerine musl libc kullandığı için bazı uyumluluk sorunları yaşanabilir
    • distroless: güvenlik odaklı production imajı; kabuk ve paket yöneticisi olmadığından debug zorlaşır ama daha güvenlidir

Kullanıcı alanı ile çekirdek arasındaki sınır

  • Temel imajdan gelenler (kullanıcı alanı)

    • Kabuk (/bin/bash, /bin/sh)
    • C kütüphanesi (glibc, musl)
    • Paket yöneticisi (apt, apk, yum)
    • Temel yardımcı araçlar (ls, cat, grep)
    • Init sistemi yapılandırması (çoğu zaman systemd'nin kendisi değil)
    • Varsayılan kullanıcılar ve gruplar (/etc/passwd)
    • Kütüphane yolları ve yapılandırma
  • Hosttan gelenler (çekirdek)

    • Süreç zamanlama ve bellek yönetimi
    • Ağ yığını (TCP/IP, yönlendirme)
    • Dosya sistemi işlemleri (okuma, yazma, mount)
    • Güvenlik özellikleri (namespace, cgroups, seccomp)
    • Aygıt sürücüleri (GPU, ağ, depolama)
    • Zaman ve saat yönetimi
    • Şifreleme ve rastgele sayı üretimi
  • Namespace'lerin yarattığı yanılsama

    • Çekirdek namespace'ler sağlayarak konteynerin yalıtılmış hissetmesini sağlar
    • Konteyner içinde PID 1 olarak görünen süreç, hostta daha yüksek bir PID'ye (ör. 45678) sahip olabilir
    • Çekirdek şu eşlemeyi korur: konteyner PID 1 → host PID 45678
    • Sanallaştırma olmadan yalıtımın nasıl çalıştığı budur

Production ortamında ne anlama geliyor

  • 1. Çekirdek açıkları tüm konteynerleri etkiler

    • Host çekirdeğinde bir açık varsa tüm konteynerler risk altındadır
    • Host'u yamalı tutmak şarttır
  • 2. Host çekirdeği konteyner özelliklerini sınırlar

    • io_uring kullanmak için host çekirdeğinin 5.1+ olması gerekir
    • eBPF özellikleri için belirli seçenekleri etkinleştirilmiş 4.15+ bir çekirdek gerekir
  • 3. glibc vs musl neden önemli

    • Alpine musl libc kullanır
    • glibc için derlenmiş bazı ikililer çalışmayabilir
    • Örnek: Alpine'de bir glibc ikilisi çalıştırılırken /lib/x86_64-linux-gnu/libc.so.6 dosyası bulunamadı hatası alınabilir
  • 4. Konteyner “OS”i tamamen düzenleyici bir kavramdır

    • Çekirdek açısından “Ubuntu konteyneri” ile “Debian konteyneri” arasında hiçbir fark yoktur
    • Her ikisi de yalnızca syscall üreten süreçlerdir

Yaygın yanlış anlamalar

  • ❌ "Konteynerler hafif VM'lerdir": konteynerler gelişmiş yalıtıma sahip süreçlerdir; VM'ler ise donanımı sanallaştırır ve ayrı çekirdek çalıştırır
  • ❌ "Her konteynerin kendine ait çekirdeği vardır": tüm konteynerler host çekirdeğini paylaşır; konteynerin “OS”i yalnızca kullanıcı alanı dosyalarından oluşur
  • ❌ "Ubuntu konteyneri çalıştırmak = Ubuntu çalıştırmak": aslında host çekirdeği üzerinde Ubuntu araçlarını çalıştırırsınız; host Debian ise gerçekte Debian çekirdeği çalışıyordur
  • ❌ "Temel imaj tam bir işletim sistemi içerir": temel imaj yalnızca minimal kullanıcı alanı araçlarını içerir; çekirdek, bootloader ve sürücüler yoktur
  • ❌ "Daha fazla konteyner = daha fazla bellek": paylaşılan katmanlar ve çekirdek sayfa önbelleği sayesinde konteynerler çoğu zaman belleği verimli biçimde paylaşır

Temel özet

  • Docker temel imajları, Linux dağıtımının kullanıcı alanı bileşenlerine ait bir dosya sistemi anlık görüntüsüdür
    • Ubuntu'yu Ubuntu gibi hissettiren ikililer, kütüphaneler ve yapılandırmalar
  • Gerçek işletim sistemi olan çekirdek host ile paylaşılır
  • Bu mimarinin mümkün kıldığı şeyler:
    • milisaniye düzeyinde başlangıç süresi (çekirdek açılışı yok)
    • çok düşük bellek ek yükü (tek çekirdek, paylaşılan sayfalar)
    • yüksek yoğunluk (host başına yüzlerce konteyner)
    • yerel performansa yakın çalışma (çekirdeğe doğrudan syscall)
  • Bunun bedeli, VM'lere göre daha zayıf yalıtımdır; konteynerler çekirdeği paylaştığı için çekirdek exploit'leri tüm konteynerleri etkiler
  • Çoğu iş yükü için bu ödünleşim buna değer

9 yorum

 
bbulbum 2026-01-22

Çekirdek + araçlar = dağıtım
O halde bu da Ubuntu sayılmaz mı..

 
sacredshine 2026-01-21

Bu yüzden Linux üzerinde doğrudan Docker'ı yapmayı deneyip dizin izolasyonu kurarak kullanıcı ve grup gibi şeyleri türlü türlü ele alan eğitimler de varmış.

 
dongho42 2026-01-21

Faydalı.

 
seunggi 2026-01-21

리눅스 네임스페이스, cgroups, 및 chroot를 사용하여 자체 Docker를 구축하세요.

Bu yüzden biraz abartarak söylemek gerekirse, chroot + cgroup = docker diye de bakılabilir gibi geldi bana

 
euphcat 2026-01-21

Aslında bu, systemd-nspawn'a biraz daha yakın ☝️🤓

 
hohemian 2026-01-22

Aslında

 
euphcat 2026-01-22

Alaycı / Kendini küçümseyen

 
crawler 2026-01-21

Gerçekten çok ilginç.

Gövde metin sanki LINUX baz alınarak açıklanmış gibi ama,
Windows'ta çalıştırıldığında bunun yazıdaki gibi WSL2 ile oluşturulan sanal çekirdeği paylaşması söz konusu oluyor, değil mi?

Eğer Docker'da bir güvenlik açığı oluşup çekirdeğe dokunulabilirse, Linux'a kıyasla bir kat daha sanallaştırma kullanan Windows'un güvenlik açısından daha güçlü sayılıp sayılamayacağını da merak ediyorum.

 
minsuchae 2026-01-22

Üstteki yorum tepkileri yüzünden biraz şaşırdım.
Ben herkesin bunu zaten bilerek kullandığını düşünmüştüm.
Linux çekirdeği hosttan gelir; geri kalanı ise Linux dağıtımlarında kullanılan araçların alınması şeklindedir.

WSL2, bildiğim kadarıyla Hyper-V üzerinde sanallaştırılarak çalışıyor.
Windows - sanal makinedeki Linux - onun içinde tekrar Container...

Temel olarak Container içindeki root, tüm sistemin gerçek root'u olmadığı için varsayılan olarak çekirdeği keyfi şekilde değiştiremez.
Yine de bir güvenlik açığı çıkarsa iş büyür.

Performans açısından bakarsak Windows tarafının biraz daha yavaş olmasının nedeni, bir kat daha sanallaştırmadan geçmesidir.