Docker & DevOps

    Docker Güvenlik En İyi Pratikleri

    Konteynerleri sertleştirmek için imaj, kullanıcı, yetenek, ağ ve sır düzeyinde uygulanacak somut önlemler.

    9 dk okuma Güncellendi: 25 Ağustos 2026

    Docker'ın en yaygın yanlış anlaşılan yanı, konteynerin bir sanal makine gibi güçlü bir yalıtım sağladığı varsayımıdır. Gerçekte konteyner, aynı çekirdeği paylaşan sıradan bir Linux sürecidir; ad alanları (namespace) ve cgroup'larla sınırlandırılmıştır ama bir hipervizör duvarı arkasında değildir. Bu yüzden Docker güvenliği, "konteyner zaten izole" varsayımını bırakıp her katmanda ayrı ayrı sınır koymakla başlar: imaj nereden geldi, süreç hangi kullanıcıyla çalışıyor, hangi çekirdek yeteneklerine sahip, dosya sistemine yazabiliyor mu, ağda kimi görebiliyor.

    Bu rehberde teorik bir güvenlik dersi yerine, bugün uygulayabileceğiniz somut önlemleri sıralayacağım: imajları sabitlemek ve taramak, konteyneri ayrıcalıksız kullanıcıyla çalıştırmak, gereksiz yetenekleri düşürmek, dosya sistemini salt okunur yapmak, Docker soketini paylaşmanın gerçek anlamını görmek, sırları imaja gömmemek ve kaynak limitleriyle hizmet dışı bırakma saldırılarını sınırlamak. Sonunda da bir konteyner denetim listesi bırakacağım.

    Tehdit Modeli: Neyi Kimden Koruyoruz#

    Somut önlemlere geçmeden önce hangi senaryolara karşı çalıştığımızı netleştirelim, çünkü her önlem farklı bir senaryoyu kapatır.

    Birinci senaryo uygulama ele geçirilmesidir: konteyner içindeki uygulamanızda bir açık bulunur ve saldırgan kod çalıştırma yeteneği kazanır. Burada amaç, saldırganın konteyner içinde yapabileceklerini en aza indirmektir — dosya yazamasın, yeni paket kuramasın, sistem çağrılarının çoğuna erişemesin.

    İkinci senaryo konteynerden kaçıştır: saldırgan çekirdek ya da çalışma zamanı açığını kullanarak host makineye çıkar. Bu, ayrıcalıklı konteynerlerde ve Docker soketi bağlanmış konteynerlerde dramatik biçimde kolaylaşır. Üçüncü senaryo tedarik zinciridir: kullandığınız temel imaj ya da bir bağımlılık kötü niyetli veya güncelliğini yitirmiş olabilir. Dördüncüsü ise yan etkidir: bir konteynerin tüm CPU'yu veya diski tüketip diğer servisleri düşürmesi.

    SenaryoAna önlemİkincil önlem
    Uygulama ele geçirilmesiRoot olmayan kullanıcıSalt okunur dosya sistemi
    Konteynerden kaçışYeteneklerin düşürülmesiRootless Docker
    Tedarik zinciriSürüm sabitleme ve taramaResmi/doğrulanmış imajlar
    Kaynak tüketimiCPU ve bellek limitleriYeniden başlatma politikası
    Sır sızıntısıÇalışma zamanı değişkenleri.dockerignore disiplini

    İmaj Güvenliği: Kaynak, Sürüm ve Tarama#

    Güvenlik imajın nereden geldiğiyle başlar. latest etiketi kullanmak, ne çalıştırdığınızı bilmemek demektir: bugün çektiğiniz imaj ile yarın çektiğiniz aynı olmayabilir ve bir sorunu geri almak imkânsız hale gelir. Sürümü açıkça sabitleyin, kritik ortamlarda ise etiket yerine içerik özetini (digest) kullanın:

    # Kötü: hangi sürüm olduğu belirsiz, her derlemede değişebilir
    FROM node:latest
    
    # İyi: sürüm sabit
    FROM node:22-alpine
    
    # En sağlam: içerik özeti, bit bit aynı imaj garantisi
    FROM node:22-alpine@sha256:0000000000000000000000000000000000000000000000000000000000000000
    

    Temel imajı küçük tutmak da doğrudan bir güvenlik önlemidir; imajda ne kadar az paket varsa saldırı yüzeyi o kadar dar olur. Bir kabuk bile bulunmayan minimal imajlar, saldırganın konteyner içinde komut çalıştırmasını ciddi biçimde zorlaştırır. Boyut küçültme tekniklerini Docker imaj boyutu optimizasyonu yazısında topladık; oradaki her adım aynı zamanda güvenlik kazancıdır.

    İmajlarınızı düzenli tarayın. Docker'ın kendi tarama komutu ya da bağımsız tarayıcılar, bilinen açıkları listeler:

    # Yerel imajdaki bilinen açıkları listele
    docker scout cves uygulama:1.0
    
    # Yalnızca yüksek ve kritik seviyeleri göster
    docker scout cves --only-severity critical,high uygulama:1.0
    
    # Temel imajı güncelleyerek kaç açığın kapanacağını öner
    docker scout recommendations uygulama:1.0
    

    Taramanın çıktısı bir görev listesidir, bir onay damgası değil. Uygulamanın kullanmadığı bir kütüphanedeki açık pratikte sömürülemeyebilir; buna karşılık düşük seviyeli görünen bir açık sizin kullanım senaryonuzda kritik olabilir. Çıktıyı okuyup değerlendirmek gerekir.

    Konteyneri Ayrıcalıksız Kullanıcıyla Çalıştırmak#

    Varsayılan olarak konteyner içindeki süreç root olarak çalışır ve bu root, host çekirdeğindeki UID 0 ile aynı sayısal kimliktir. Kullanıcı ad alanı eşlemesi devrede değilse, konteynerden kaçmayı başaran bir süreç host'ta root ayrıcalıklarıyla devam eder. Bunu kapatmanın en basit yolu imajda bir kullanıcı tanımlamaktır:

    FROM python:3.12-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    COPY . .
    
    # Ayrıcalıksız kullanıcı oluştur ve devret
    RUN useradd --create-home --uid 10001 uygulama \
     && chown -R uygulama:uygulama /app
    USER uygulama
    
    CMD ["python", "app.py"]
    

    İmajı değiştiremiyorsanız çalışma zamanında da zorlayabilirsiniz. Ayrıca ayrıcalık yükseltmeyi tamamen kapatmak tek satırlık ve son derece etkili bir önlemdir:

    services:
      app:
        image: uygulama:1.0
        user: "10001:10001"
        security_opt:
          # setuid ikili dosyalarıyla ayrıcalık kazanmayı engeller
          - no-new-privileges:true
    

    no-new-privileges bayrağı, konteyner içinde bulunan bir setuid programının süreci yükseltmesini engeller. Uygulamalarınızın büyük çoğunluğu bu yeteneğe ihtiyaç duymaz, dolayısıyla bunu varsayılan yapmakta hiçbir sakınca yoktur.

    Ayrıcalıklı mod ise tam tersi uçtur. --privileged bayrağı neredeyse tüm yalıtımı kaldırır: konteyner host aygıtlarına erişir, tüm yetenekleri alır ve pratik olarak host'a eşdeğer yetkiye kavuşur. Belirli bir aygıta erişim gerekiyorsa --device ile yalnızca o aygıtı verin; --privileged bir çözüm değil, sorunun ertelenmesidir.

    Yetenekler, Salt Okunur Dosya Sistemi ve Ağ#

    Linux, root yetkisini "yetenek" (capability) adı verilen parçalara böler. Docker varsayılan olarak bunlardan bir alt kümesini verir, ama tipik bir web uygulamasının bunların neredeyse hiçbirine ihtiyacı yoktur. En sağlam yaklaşım hepsini düşürüp yalnızca gerekeni geri eklemektir:

    services:
      web:
        image: nginx:alpine
        cap_drop:
          - ALL
        cap_add:
          # 1024 altındaki portu bağlamak için gerekli
          - NET_BIND_SERVICE
        read_only: true
        tmpfs:
          # Salt okunur kökte yazılabilir alan gereken yerler
          - /tmp
          - /var/cache/nginx
          - /var/run
        security_opt:
          - no-new-privileges:true
    

    read_only: true ayarı, konteynerin kök dosya sistemini yazılamaz yapar. Bu, ele geçirilmiş bir uygulamanın konteyner içine araç indirip çalıştırmasını, kalıcılık kurmasını ve dosya değiştirmesini engeller. Uygulamanızın gerçekten yazması gereken dizinleri tmpfs ile bellekte tutar ya da adlandırılmış hacim bağlarsınız; hangi dizinlerin yazma istediğini bulmak için konteyneri salt okunur başlatıp logdaki hataları izlemek en hızlı yöntemdir.

    Ağ tarafında kural basittir: yalnızca dışarıdan erişilmesi gereken portu yayımlayın. Veritabanı, önbellek ve iç servisler yayımlanmamalıdır; aynı Docker ağındaki konteynerler birbirini zaten servis adıyla bulur. Yayımlamak zorundaysanız arayüzü sınırlayın:

        ports:
          # Yanlış: tüm arayüzlerde, internete açık
          # - "5432:5432"
          # Doğru: yalnızca host'un kendisinden erişilir
          - "127.0.0.1:5432:5432"
    

    Sunucudaki gerçek durumu görmek için dışarıdan bir tarama yapmak, yapılandırmayı okumaktan daha kesin sonuç verir:

    # Hangi konteyner portları dışarıya açık
    docker ps --format 'table {{.Names}}\t{{.Ports}}'
    
    # Host üzerinde dinlenen portlar
    ss -ltnp | grep docker
    

    Docker'ın kendi kurallarının güvenlik duvarınızı atlayabildiğini unutmayın: Docker iptables zincirine kendi kurallarını ekler ve yayımlanan bir port, sunucudaki basit bir güvenlik duvarı politikasına rağmen dışarıdan erişilebilir olabilir. Ağ mimarisini kurarken Docker network yapılandırma yazısındaki ayrımları göz önünde bulundurun.

    Docker Soketi ve Sır Yönetimi#

    Bir konteynere /var/run/docker.sock bağlamak, o konteynere host üzerinde root eşdeğeri yetki vermek demektir. Sebebi basittir: soket üzerinden yeni bir konteyner oluşturabilen bir süreç, host kök dizinini bağlayan ayrıcalıklı bir konteyner başlatıp her şeyi okuyup yazabilir. Ters proxy'ler ve izleme araçları bu soketi istediği için bu risk çok yaygın biçimde kabullenilir.

    Kaçınılmazsa şu üç önlemi alın: soketi :ro ile salt okunur bağlayın, yalnızca güvendiğiniz ve doğrulanmış imajlara verin, mümkünse soketi doğrudan değil yalnızca gerekli çağrılara izin veren bir proxy üzerinden sunun. Soket izinleriyle ilgili gündelik sorunları Docker daemon socket permission denied yazısında ele aldık; oradaki "kullanıcıyı docker grubuna ekleme" çözümünün de aslında o kullanıcıya root eşdeğeri yetki verdiğini bilerek uygulayın.

    Sırlar konusunda tek kural vardır: sır imaja girmez. ENV ile yazılan bir parola imaj katmanlarında kalıcıdır ve imajı çeken herkes okuyabilir; sonradan silmeniz eski katmanı yok etmez.

    # İmajda gömülü sır var mı diye kontrol edin
    docker history --no-trunc uygulama:1.0 | grep -Ei "password|secret|token|key"
    
    # Çalışan konteynerin ortam değişkenlerini denetleyin
    docker inspect uygulama --format '{{range .Config.Env}}{{println .}}{{end}}'
    

    Doğru yöntem, sırları çalışma zamanında vermektir: izinleri 600 olan bir env_file, orkestrasyon katmanının sır mekanizması ya da dosya olarak bağlanan bir sır hacmi. Rastgele ve yeterince uzun değerler üretmek için parola üretici aracımızı kullanabilirsiniz.

    Denetim Listesi ve Sık Yapılan Hatalar#

    Aşağıdaki liste, yayına almadan önce her konteyner için hızlıca geçilebilir:

    1. Temel imaj sürümü sabitlenmiş mi, latest kullanılıyor mu?
    2. USER satırı var mı, süreç root olarak mı çalışıyor?
    3. no-new-privileges ayarlı mı?
    4. Gereksiz yetenekler düşürülmüş mü (cap_drop: ALL)?
    5. Kök dosya sistemi salt okunur yapılabilir mi?
    6. Yalnızca gerekli portlar, mümkünse yalnızca 127.0.0.1 üzerinde mi yayımlanıyor?
    7. Docker soketi bağlanmış mı, gerçekten gerekli mi?
    8. Sırlar imajda mı, çalışma zamanında mı veriliyor?
    9. CPU ve bellek limitleri tanımlı mı?
    10. İmaj son bir ay içinde tarandı ve güncellendi mi?

    Sahada en sık gördüğüm hatalar da şunlar: her şeyi root çalıştırmak (imaja tek satır USER eklemek çoğu durumda yeterlidir), sorun çözmek için --privileged vermek (gerçek ihtiyaç genellikle tek bir yetenek ya da tek bir aygıttır), veritabanı portunu dışarı açmak (iç ağ zaten yeterlidir), .env dosyasını imaja kopyalamak (.dockerignore bunu kapatır) ve imajları hiç güncellememek (aylar önce derlenmiş bir imaj, o gün bilinen tüm açıkları hâlâ taşır). Konteyner yaşam döngüsünü düzenli tutmak, bakımsız kalan imajların birikmesini de önler; disk ve artık temizliği için Docker diski doldurdu, nasıl temizlenir yazısı işinizi görecektir.

    Sıkça Sorulan Sorular#

    Konteyner sanal makine kadar güvenli mi#

    Hayır, aynı düzeyde değildir. Sanal makineler ayrı bir çekirdek çalıştırır ve hipervizör tarafından donanım düzeyinde ayrılır; konteynerler ise host çekirdeğini paylaşır. Çekirdekte bulunan bir açık, teorik olarak tüm konteynerleri etkileyebilir. Bu, konteynerlerin güvensiz olduğu anlamına gelmez; doğru sertleştirmeyle çok makul bir güvenlik seviyesine ulaşırsınız, ama yalıtımı sanal makineyle eşdeğer saymak yanlış olur.

    Konteyneri root ile çalıştırmak gerçekten sorun mu#

    Evet, çünkü konteynerdeki root ile host'taki root çoğu kurulumda aynı sayısal kimliktir. Konteynerden kaçış sağlayan bir açık bu durumda doğrudan host'ta tam yetki demektir. Ayrıca root olarak çalışan bir süreç, bağlı hacimlerdeki dosyaları sahibi kim olursa olsun değiştirebilir. İmaja tek satır USER eklemenin maliyeti neredeyse sıfırken kazancı büyüktür.

    Docker soketini izleme aracına bağlamak zorunda mıyım#

    Çoğu izleme ve ters proxy aracı konteyner listesini okumak için bu soketi ister. Alternatif, soketi doğrudan vermek yerine önüne yalnızca okuma çağrılarına izin veren bir aracı koymaktır; böylece araç konteyner listesini görür ama yeni konteyner oluşturamaz. Bu ek katman biraz karmaşıklık getirir, ancak host'a root eşdeğeri yetki vermekten çok daha iyidir.

    İmajlarımı ne sıklıkla güncellemeliyim#

    Temel imajları ayda bir gözden geçirmek makul bir ritimdir; kritik bir açık duyurulduğunda ise beklemeden yeniden derlemek gerekir. Otomatik bir derleme hattınız varsa haftalık yeniden derleme planlamak, güvenlik yamalarının kendiliğinden gelmesini sağlar. Unutmayın ki imaj bir kez derlendikten sonra donar; sunucuda apt upgrade çalıştırmak konteyner içindekini güncellemez.

    Docker Compose'da güvenlik ayarları nasıl uygulanır#

    Bu rehberdeki tüm ayarların compose karşılığı vardır: user, cap_drop, cap_add, read_only, tmpfs, security_opt ve kaynak limitleri. Bunları her servise tek tek yazmak yerine ortak bir tanım bloğu oluşturup YAML çapaları ile tekrar kullanabilirsiniz. Böylece yeni bir servis eklendiğinde güvenlik ayarlarının unutulma ihtimali azalır.

    Rootless Docker kullanmalı mıyım#

    Tek sunucuda kendi uygulamalarınızı çalıştırıyorsanız ve ek yapılandırma yükünü kabul ediyorsanız kesinlikle değerlidir: kaçış senaryosunun etkisini sıradan bir kullanıcının yetkisiyle sınırlar. Ancak bazı kısıtları vardır; 1024 altındaki portlar, bazı ağ ve depolama sürücüleri ek ayar ister. Ayrıntılı kurulum ve kısıtlar için Rootless Docker kurulumu yazısına bakabilirsiniz.

    Kapanış#

    Docker güvenliğinde en büyük kazancı getiren adımlar en basit olanlardır: imaj sürümünü sabitlemek, USER satırıyla root'tan çıkmak, no-new-privileges ve cap_drop: ALL eklemek, kök dosya sistemini salt okunur yapmak, yalnızca gerekli portu ve mümkünse yalnızca localhost'a yayımlamak, sırları imaja değil çalışma zamanına bırakmak ve imajları düzenli tarayıp yeniden derlemek. Bu yedi maddeyi standart hâline getirdiğinizde, kalan riskler çok daha dar bir alana sıkışır.

    Konteyner altyapınızı barındıracağınız yerde tam yetki ve kendi güvenlik duvarı kurallarınız olmalıdır; VDS ve bulut sunucu paketlerimiz bu senaryo için uygundur. Uygulama katmanındaki saldırıları filtrelemek için WAF ve hacimli saldırılara karşı DDoS koruma hizmetlerimizi konteyner sertleştirmesinin tamamlayıcısı olarak düşünebilir, sunucu bakımını ve güncelleme takibini sunucu yönetimi hizmetimize bırakabilirsiniz.

    DockerGüvenlikDevOps

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.