Yazılarımız

Veri Akademi

DOCKER GÜVENLİĞİ: IMAGE SCAN, LEAST PRİVİLEGE VE RUNTİME RİSKLERİ

Docker’ı üretimde çalıştırmak kolay; asıl zor olan, onu güvenli ve sürdürülebilir şekilde işletmek. Bir imajın içine yanlışlıkla sızan gizli anahtarlar, gereksiz root yetkileriyle açılan kapılar veya runtime’da kaçırılan bir konfigürasyon hatası, birkaç dakikada ciddi bir olaya dönüşebilir.

Bu yazıda Docker güvenliği yaklaşımını “build → registry → deploy → runtime” hattının tamamı için ele alacağız. Image scan ile başlayıp “least privilege” prensibiyle devam edecek, en sonda da runtime risklerini azaltmak için pratik hardening adımlarını toparlayacağız.

Hedef, mükemmel güvenlik değil; ölçülebilir ve tekrarlanabilir kontrollerle saldırı yüzeyini küçültmek ve olay anında etkileri sınırlamak. Yazının sonunda ayrıca, CI/CD’ye uyumlu bir kontrol listesi ve kod örnekleri bulacaksınız.


Tehdit modeli: Nereden saldırılır, nerede kırılır?

Docker ekosisteminde riskler genellikle üç kaynaktan beslenir: imaj tedarik zinciri (supply chain), yanlış yetkilendirme/izolasyon ve runtime zafiyetleri. Güvenlik çalışmalarını “her şeyi kilitle” yaklaşımı yerine, iş yükünüzün tehdit modeline göre önceliklendirmek daha sonuç odaklıdır.

Başlıca saldırı yüzeyleri

  • Base image seçimleri: Güncel olmayan paketler, bilinmeyen kaynaklar, şüpheli tag kullanımı
  • Build çıktısı: Yanlış kopyalanan dosyalar, gizli anahtarların layer’a girmesi, gereksiz araçların taşınması
  • Registry ve imza: Kim üretti, hangi commit’ten çıktı, değiştirildi mi?
  • Çalıştırma parametreleri: Yetkiler, capabilities, mount’lar, network, kullanıcı
  • Host ve runtime: Kernel seviyesinde kaçış (escape) ihtimalleri, syscalls, cgroups, namespaces

Önceliklendirme: “Olasılık × Etki”

Örneğin internete açık bir API servisi için “root yetkisi” ve “host volume mount” daha yüksek etki yaratır. İç ağda çalışan kısa ömürlü batch job’larda ise en büyük risk, imajın içine gömülen kimlik bilgileri veya eski bir dependency olabilir. Bu yüzden, güvenlik kontrollerini risk matrisiyle uyumlu bir sıraya koymak önemlidir.

CI/CD boru hattında imaj üretimi, zafiyet taraması, SBOM doğrulaması ve registry yayın adımlarını gösteren akış

Image scan: Zafiyet taraması, yanlış konfigürasyon ve sürpriz bağımlılıklar

Image scan, registry’ye giden imajın içindeki paketleri, kütüphaneleri ve bilinen CVE’leri görünür kılar. Ancak tarama yalnızca “CVE listesi” değildir; yanlış permission’lar, gereksiz paketler, riskli config değerleri ve hatta secret sızıntıları da bu katmanda yakalanabilir.

Zafiyet taraması neyi çözer, neyi çözmez?

Tarama, bilinen zafiyetleri (CVE) yakalamada güçlüdür; fakat “zero-day” veya uygulama mantığı hatalarını çözmez. Ayrıca sonuçların kalitesi; base image, kullanılan distro, paket yöneticisi ve SBOM üretimine bağlıdır. Bu nedenle tarama çıktısını “bloklayıcı” mı “bilgilendirici” mi yapacağınızı, servis kritikliğine göre belirlemek gerekir.

CI’da Trivy ile tarama örneği

Aşağıdaki örnek, imajı hem zafiyet hem de yanlış konfigürasyon açısından tarar; kritik seviyede bulgu varsa pipeline’ı fail eder. Bu yaklaşım, “shift-left” güvenlik için hızlı bir başlangıçtır.

# Image vulnerability + misconfiguration scan (CI example)
trivy image --severity HIGH,CRITICAL --exit-code 1   --ignore-unfixed   --scanners vuln,misconfig   myorg/myapp:sha-1a2b3c

# Optional: also scan for secrets in layers (can be noisy; tune gradually)
trivy image --scanners secret --exit-code 0 myorg/myapp:sha-1a2b3c

Burada önemli iki pratik nokta var: (1) “ignore-unfixed” ile yamalanamayan paketler için gereksiz kırılmaları azaltırsınız; (2) secret taramasını ilk etapta raporlayıp, daha sonra kural seti olgunlaştıkça bloklayıcı yapabilirsiniz.

Supply chain güvenliği: Base image, tag disiplini, SBOM ve imaj imzalama

Birçok olay, uygulama kodundan değil; “kimden aldığınız imaj” ve “hangi versiyonu çektiğiniz” gibi tedarik zinciri kararlarından çıkar. “latest” gibi belirsiz tag’ler, deterministik olmayan deploy’lar üretir. Üretimde aynı imajı koştuğunuzdan emin olmanın yolu, digest ve imza disiplinidir.

Base image seçimi ve minimalizm

Gereksiz paketler saldırı yüzeyini büyütür. Multi-stage build ile derleme araçlarını runtime imajına taşımamak, hem boyutu hem riski azaltır. Ayrıca mümkünse “distroless” veya minimal imaj yaklaşımı, shell ve paket yöneticisi gibi araçları runtime’dan kaldırarak saldırganın işini zorlaştırır.

Digest pinning: “Aynı imaj mı koşuyoruz?”

Tag yerine digest kullanmak (ör. sha256:...) imajın içeriğini sabitler. Böylece “bugün çektiğim imaj” ile “yarın çektiğim imaj” aynı olur. Bu, audit ve incident yönetiminde kritik avantaj sağlar.

SBOM ve imza: Kanıt zinciri oluşturma

SBOM (Software Bill of Materials), imajın hangi bağımlılıkları içerdiğini makine tarafından okunabilir şekilde kayıt altına alır. İmaj imzalama ise bu artefaktın yetkili bir kaynak tarafından üretildiğini doğrular. Kurumsal ölçekte, registry’de yalnızca imzalı imajların çalışmasına izin vermek, supply chain riskini ciddi şekilde düşürür.

Least privilege: Kullanıcı, capabilities, filesystem ve network yetkilerini daraltma

En az ayrıcalık (least privilege), konteynerin yalnızca ihtiyacı olan yetkilerle çalışmasını sağlar. Bu prensip, zafiyet olsa bile etki alanını küçültür. Docker tarafında pratik karşılığı; root olmayan kullanıcı, minimum capabilities, salt-okunur dosya sistemi, daraltılmış mount’lar ve kontrollü ağ erişimidir.

Root yerine uygulama kullanıcısı

Birçok imaj varsayılan olarak root ile gelir. Oysa uygulama gerçekten root yetkisi istemiyorsa, UID/GID ile çalıştırmak daha güvenlidir. Rootless container yaklaşımı da ek bir koruma katmanı sağlar. Bu adım, runtime’da host kaynaklarına erişimi zorlaştırır.

Rootless yaklaşımıyla çalışan bir serviste kısıtlı yetkiler, salt okunur dosya sistemi ve minimal capabilities kullanımını anlatan düzen

Docker run ile yetki daraltma örneği

Aşağıdaki örnek, konteyneri non-root kullanıcıyla çalıştırır, dosya sistemini read-only yapar, gereksiz capabilities’i düşürür ve yalnızca gerekli olanı ekler. Uygulamanıza göre listeyi uyarlamalısınız.

docker run --rm -d   --name myapp   --user 10001:10001   --read-only   --tmpfs /tmp:rw,noexec,nosuid,size=64m   --cap-drop ALL   --cap-add NET_BIND_SERVICE   --security-opt no-new-privileges:true   -p 8080:8080   myorg/myapp:sha-1a2b3c

Burada no-new-privileges özellikle değerlidir: prosesin setuid/setgid gibi mekanizmalarla sonradan yetki yükseltmesini engeller. “read-only + tmpfs” kombinasyonu ise saldırganın kalıcılık elde etmesini zorlaştırır.

Runtime riskleri: Kaçış senaryoları, kernel saldırıları ve gözden kaçan konfigürasyonlar

Runtime güvenliği, konteyner çalışırken oluşabilecek riskleri azaltmayı hedefler. İmaj taraması “ne taşıyoruz?” sorusunu cevaplar; runtime ise “nasıl çalıştırıyoruz?” sorusunu. Çoğu kritik olay, yanlış runtime parametreleri ve host üzerinde geniş etkiler bırakan hatalardan doğar.

Tehlikeli desenler: privileged, host mount ve host network

--privileged ile çalıştırmak, izolasyon duvarlarını inceltir ve escape ihtimalini artırır. Benzer şekilde “/var/run/docker.sock” gibi host soketlerini mount etmek, konteyner içinden Docker API’ye erişim anlamına gelebilir; bu da pratikte host üzerinde tam kontrol riskini doğurur. Host network, servis izolasyonunu zayıflatır ve trafik görünürlüğünü azaltır.

Seccomp ve AppArmor ile sistem çağrısı kısıtlama

Seccomp profilleri, prosesin hangi sistem çağrılarını kullanabileceğini sınırlar; AppArmor ise dosya ve kaynak erişimi üzerinde ek bir kontrol sağlar. Varsayılan profiller iyi bir başlangıçtır; yüksek riskli iş yüklerinde özelleştirilmiş profillerle daha sıkı bir izolasyon sağlanabilir.

Linux çekirdeği üzerinde seccomp filtreleri ve AppArmor profilleriyle konteyner sistem çağrılarının ve dosya erişiminin sınırlanmasını gösteren yapı

Gözlemlenebilirlik: Runtime’da anomali yakalama

Yalnızca kısıtlamak yetmez; anomaliyi yakalamak gerekir. Beklenmeyen outbound bağlantılar, bilinmeyen binary çalıştırılması, olağandışı syscalls ve yeni mount girişimleri gibi sinyaller; runtime tehdit tespitinin temelini oluşturur. Bu sinyallerin toplanması için eBPF tabanlı yaklaşımlar, host agent’ları veya merkezi log/metric pipeline’ları kullanılabilir.

Güvenli Dockerfile: Katman hijyeni, secret sızıntısı ve yeniden üretilebilir build

Dockerfile, güvenliğin ilk ve en ucuz katmanıdır. Yanlış yazılmış bir satır, tarama araçlarının yakalayacağı onlarca bulgunun kök nedeni olabilir. Hedef; minimal runtime, deterministik build ve secret’ların asla layer’a girmemesidir.

Multi-stage build ile minimal runtime örneği

Aşağıdaki örnek, derleme araçlarını ilk aşamada bırakır, runtime aşamasında yalnızca gerekli artefaktı taşır. Ayrıca non-root kullanıcıyla çalışır ve dosya izinlerini kontrollü ayarlar.

# Build stage
FROM golang:1.22-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app

# Runtime stage
FROM gcr.io/distroless/static-debian12:nonroot
WORKDIR /app
COPY --from=build /out/app /app/app
USER 65532:65532
ENTRYPOINT ["/app/app"]

Secret yönetimi için ise “build arg ile secret geçmek” gibi pratikler risklidir. CI ortamında secret’ların yalnızca runtime’da inject edilmesi ve build cache/layer’lara yazılmaması temel kural olmalıdır. Ayrıca dependency güncellemeleri için periyodik otomasyon, CVE birikmesini önler.

Politika ve otomasyon: Gate’ler, istisnalar ve ölçülebilir güvenlik

Güvenliği sürdürülebilir kılan şey, otomasyon ve ölçümdür. “Bugün güvenli” olmak değil, “her deploy’da aynı kontrolleri uygulamak” önemlidir. Bunun için CI’da tarama gate’leri, registry’de imza doğrulaması ve deploy aşamasında politika kontrolü bir arada çalışmalıdır.

Pratik bir kontrol listesi

  • Base image: Güvenilir kaynak + düzenli güncelleme + minimal yaklaşım
  • Tag ve digest: Üretimde digest pinning, “latest” kullanımından kaçınma
  • Image scan: HIGH/CRITICAL bulgularda fail; istisnalar için süreli waiver
  • SBOM: Her build’de üretim, registry’ye ek artefakt olarak yayın
  • İmaj imzalama: Üretime giden artefaktların imzalı olması
  • Least privilege: Non-root, cap-drop, read-only, no-new-privileges
  • Runtime: Seccomp/AppArmor profilleri, host mount kısıtları
  • Gözlemlenebilirlik: Log/metric/trace standardı, anomali alarmları

İstisna yönetimi: “Waiver” kültürü

Bazı CVE’ler kısa vadede düzeltilemeyebilir. Bu noktada “her şeyi kapat” yerine; istisnayı kayıt altına alıp süre vermek, risk sahibini belirtmek ve bir sonraki sprint’e planlamak daha gerçekçi bir yaklaşımdır. Böylece tarama araçları güven kaybetmez; ekip de alarm yorgunluğuna düşmez.

Üretimde operasyon: Incident hazırlığı ve hızlı toparlanma

En iyi kontroller bile sıfır risk sunmaz. Bu yüzden incident hazırlığı, Docker güvenliğinin ayrılmaz parçasıdır. Hangi imajın nerede koştuğu, hangi digest’in hangi release’e denk geldiği ve hangi konfigürasyonla çalıştığı net değilse, olay yönetimi uzar ve maliyet artar.

İzlenebilirlik: “Hangi commit, hangi imaj, hangi pod?”

Release sürecinizde commit SHA, imaj digest’i ve deploy edilen ortam arasında izlenebilir bir ilişki kurun. Bu ilişki, rollback kararlarını hızlandırır ve adli analizde “hangi sürüm etkilendi?” sorusunu netleştirir.

Hızlı aksiyon: Kapat, izole et, yeniden yayınla

Şüpheli bir durum oluştuğunda; ilgili servisleri izole etmek (network policy / firewall), etkilenen imajları bloklamak, yeni imajı tarayıp imzalayarak yayınlamak ve sadece doğrulanmış artefaktları yeniden dağıtmak en sağlam akıştır. Bu yaklaşımın eğitimli ve otomatik hale getirilmesi, olgun DevSecOps pratiğinin temelidir.


Docker güvenliğini “tek seferlik hardening” olarak değil, sürekli bir yaşam döngüsü olarak düşünün: build’de tarayın, registry’de doğrulayın, deploy’da kısıtlayın, runtime’da izleyin. Bu yaklaşım hem saldırı yüzeyini küçültür hem de ekiplerin günlük akışını bozmadan güvenlik seviyesini yükseltir.

Bu konuları uygulamalı senaryolarla derinleştirmek ve kurumsal bir yol haritası oluşturmak için Docker Eğitimi içeriğine de göz atabilirsiniz.

 VERİ AKADEMİ