Docker güvenliği, yalnız imajda bilinen CVE bulunup bulunmadığını kontrol etmekten ibaret değildir. Güvenli bir konteyner; güvenilir ve küçük bir imajla başlar, kök olmayan kullanıcıyla çalışır, gereksiz Linux yeteneklerini bırakır, seccomp ve AppArmor/SELinux sınırlarını korur, dosya sistemini mümkün olduğunca salt okunur kullanır, sırları imajdan ayırır ve CPU/bellek/PID kaynaklarını sınırlar.

Konteyner bir sanal makine değildir. Aynı ana makinenin çekirdeğini paylaşır; namespace ve cgroup mekanizmaları süreç, ağ, dosya sistemi ve kaynak görünürlüğünü ayırır. Bu nedenle uygulamanın konteyner içinde “root” olması, yanlış mount, --privileged, Docker socket erişimi veya geniş Linux capabilities ile birleştiğinde ana sistem için ciddi risk oluşturabilir.

Bu rehber; Dockerfile, Docker Compose ve `docker run` seviyesinde uygulanabilir bir container hardening modeli sunar. Rootless mode ile userns-remap farkını, `cap_drop`, `no-new-privileges`, seccomp, AppArmor, read-only root filesystem, tmpfs, secrets, kaynak limitleri, ağ yüzeyi, imaj sabitleme ve üretim doğrulamasını adım adım açıklar.

Docker tehdit modeli: Neyi koruyoruz?

Bir konteynerin güvenlik sınırı dört ana alanda değerlendirilmelidir:


  • İmaj ve tedarik zinciri: Base image, paketler, derleme aracı, bağımlılıklar ve registry kaynağı.
  • Çalışma zamanı yetkileri: Kullanıcı kimliği, capabilities, seccomp, LSM profili, cihazlar ve ayrıcalıklı mod.
  • Ana sistemle temas: Bind mount'lar, Docker socket, host network/PID/IPC namespace ve çekirdek yüzeyi.
  • Operasyonel dayanıklılık: CPU, bellek, PID, disk yazımı, log hacmi, sır yönetimi ve izleme.



En gerçekçi hedef “konteyner asla ele geçirilemez” değildir. Uygulama içinde uzaktan kod çalıştırma oluşsa bile saldırganın yetkisini, erişebildiği dosya ve ağları, yeni ayrıcalık kazanma seçeneklerini ve ana sisteme sıçrama ihtimalini azaltan katmanlı savunma kurulmalıdır.

En riskli Docker yapılandırmaları

YapılandırmaRiskGüvenli yaklaşım
--privilegedNeredeyse tüm cihaz ve kernel yetkilerini açarKullanmayın; gereken tek capability veya device erişimini belirleyin
/var/run/docker.sock mountKonteynerden Docker daemon kontrolü sağlayabilirSoketi uygulama konteynerine bağlamayın; dar yetkili aracı katman kullanın
--network hostAğ namespace ayrımını kaldırırKullanıcı tanımlı bridge ağı ve yalnız gerekli port yayını
--pid host / --ipc hostAna sistem süreç/IPC yüzeyini açarVarsayılan ayrı namespace'leri koruyun
cap_add: ALLKök yetkisini genişletircap_drop: ALL; yalnız ölçülen tekil ihtiyaçları ekleyin
seccomp=unconfinedSistem çağrısı filtresini kapatırDocker'ın varsayılan seccomp profilini koruyun
apparmor=unconfinedLSM dosya/işlem sınırlarını kaldırırdocker-default veya test edilmiş özel profil
/:/host gibi bind mountAna dosya sistemine yazma erişimi verirDar yol, read_only mount ve sahiplik kontrolü
Sınırsız bellek/PIDHizmet reddi ve ana sistem kararsızlığımemory, cpus ve pids_limit tanımlayın
İmajda/env'de sırKatman, geçmiş, inspect veya loglardan sızıntıBuildKit/Compose/Swarm secrets ve harici secret manager


Tek bir riskli seçenek başka kontrolleri anlamsızlaştırabilir. Örneğin konteyneri `USER 10001` ile çalıştırmak iyi bir adımdır; ancak Docker socket yazılabilir bağlandıysa uygulama yeni ayrıcalıklı konteyner başlatarak sınırı aşabilir.

1. Güvenli Dockerfile: Küçük, tekrarlanabilir ve root olmayan imaj

Üretim imajında derleyici, paket yöneticisi, test aracı ve kaynak kod gibi çalışmada gerekmeyen bileşenleri bırakmayın. Multi-stage build, derleme ve çalışma katmanını ayırır:

CODE TERMINAL
# syntax=docker/dockerfile:1
FROM node:24-bookworm-slim AS build
WORKDIR /src
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
RUN npm run build && npm prune --omit=dev

FROM node:24-bookworm-slim AS runtime
ENV NODE_ENV=production
WORKDIR /app

RUN groupadd --system --gid 10001 appgroup \
 && useradd --system --uid 10001 --gid appgroup \
    --home-dir /nonexistent --shell /usr/sbin/nologin appuser

COPY --from=build --chown=10001:10001 /src/dist ./dist
COPY --from=build --chown=10001:10001 /src/node_modules ./node_modules
COPY --chown=10001:10001 package.json ./

USER 10001:10001
EXPOSE 3000
CMD ["node", "dist/server.js"]


Bu örnekte üretim katmanına yalnız çalıştırma için gereken dosyalar taşınır ve süreç sabit UID/GID ile çalışır. UID'yi açıkça vermek, imaj yeniden oluşturulduğunda rastgele kullanıcı numarası değişimini önler. Uygulama 1024 altındaki porta bağlanmak zorunda değilse `CAP_NET_BIND_SERVICE` ihtiyacı da doğmaz; içeride 3000 gibi yüksek port kullanılıp dışarıda 443'e eşlenebilir.

Base image etiketi değişebilir. Tekrarlanabilirlik ve tedarik zinciri bütünlüğü için sürüm etiketini digest ile sabitlemek mümkündür:

CODE TERMINAL
FROM node:24-bookworm-slim@sha256:


Digest'i örnek bir değerle tahmin etmeyin. CI, güvenilir registry'den gerçek digest'i çözüp politika denetiminden geçirmeli; güncelleme botu veya kontrollü süreç yeni digest için inceleme kaydı oluşturmalıdır. Digest sabitlemek yamaları otomatik getirmez, bu nedenle düzenli yeniden oluşturma zorunludur.

2. Build context ve sırları imajdan ayırma

`.dockerignore`, gereksiz ve hassas dosyaların build context'e girmesini önler:

CODE TERMINAL
.git
.env
.env.*
*.pem
*.key
secrets/
node_modules
coverage
tmp
Dockerfile*
compose*.yml


Liste uygulamaya göre gözden geçirilmelidir; build için gereken dosyayı yanlışlıkla dışlamayın. Asıl güvenlik ilkesi, özel anahtar, `.env`, bulut kimlik bilgisi ve üretim sertifikasının Docker daemon'a bile gönderilmemesidir.

`ARG TOKEN=...` veya `ENV API_KEY=...` derleme sırrı için uygun değildir. Değer imaj geçmişinde, katmanda, hata çıktısında veya CI logunda kalabilir. BuildKit secret mount kullanın:

CODE TERMINAL
# syntax=docker/dockerfile:1
FROM node:24-bookworm-slim AS build
WORKDIR /src
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm ci


CODE TERMINAL
docker build \
  --secret id=npmrc,src=/secure/path/npmrc \
  -t registry.example/app:1.4.2 .


Bu kullanım sırrı yalnız ilgili `RUN` adımı sırasında geçici dosya olarak sunar; Dockerfile'a veya son katmana kopyalanmamalıdır. CI loglarında komut izleme ve hata ayrıntılarının sırrı yazdırmadığı ayrıca test edilmelidir.

3. Rootless mode ve userns-remap farkı

Rootless mode, hem Docker daemon'u hem de konteynerleri root olmayan kullanıcı içinde çalıştırır. Docker belgelerine göre amaç daemon ve container runtime açıklarının etkisini azaltmaktır. `newuidmap` ve `newgidmap` dışında setuid veya file capability gerektirmeden user namespace kullanır.

userns-remap ise konteyner içindeki UID/GID değerlerini ana sistemde ayrıcalıksız bir aralığa eşler; fakat Docker daemon root olarak çalışmaya devam eder. İki yöntem aynı şey değildir.

ÖzellikRootless modeuserns-remap
Docker daemonRoot olmayan kullanıcıRoot
Konteyner kimliğiUser namespace içinde eşlenirAna sistemde subordinate UID/GID aralığına eşlenir
Daemon açığının etkisiDaha dar ayrıcalık hedeflenirRoot daemon riski devam eder
UyumlulukAğ, cgroup, düşük port ve depolama sınırlamaları olabilirBind mount sahipliği ve mevcut volume geçişi dikkat ister
KullanımUyumlu genel iş yüklerinde güçlü varsayılanRootful daemon gereken ortamlarda kimlik yalıtımı


Rootless modda doğrulama:

CODE TERMINAL
docker context show
docker info --format '{{json .SecurityOptions}}'
docker info | sed -n '/Security Options/,+8p'


Çıktıda `rootless`, `seccomp` ve uygun cgroup seçenekleri görülmelidir. Yalnız istemcinin “rootless” isimli context'te olması yeterli değildir; bağlanılan daemon güvenlik seçeneklerinden doğrulanmalıdır.

Mevcut rootful kurulumdan rootless'a geçiş; volume sahipliği, bind mount izinleri, 1024 altı portlar, overlay depolama, cgroup v2 ve izleme araçları açısından pilot test gerektirir. Üretim sunucusunda kontrolsüz geçiş yapmayın.

4. Linux capabilities: Önce hepsini bırak, sonra gerekeni ekle

Linux capabilities, root yetkisini daha küçük parçalara böler. Docker varsayılan olarak bir kısmını kapatır; ancak genel web uygulamalarının çoğu kalanların da büyük bölümüne ihtiyaç duymaz.

Komut satırı örneği:

CODE TERMINAL
docker run --rm \
  --user 10001:10001 \
  --cap-drop ALL \
  --security-opt no-new-privileges=true \
  registry.example/app:1.4.2


Uygulama gerçekten düşük porta bağlanmak zorundaysa yalnız gereken capability eklenebilir:

CODE TERMINAL
docker run --rm \
  --user 10001:10001 \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --security-opt no-new-privileges=true \
  registry.example/app:1.4.2


`SYS_ADMIN` çok geniş bir yetki kümesidir ve genellikle “yeni root” olarak anılır. Mount, namespace ve kernel yüzeyleriyle ilişkili riskler nedeniyle sıradan uygulama konteynerine verilmemelidir. `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` ve `SYS_RAWIO` gibi yetkiler de somut ihtiyaç ve tehdit analizi olmadan eklenmemelidir.

`no-new-privileges`, süreç ve çocuklarının setuid/setgid ikilileri veya file capabilities üzerinden yeni ayrıcalık kazanmasını engeller. Bu seçenek uygulamanın mevcut yetkilerini otomatik düşürmez; `USER` ve `cap-drop` ile birlikte kullanılmalıdır.

5. Seccomp: Sistem çağrısı yüzeyini daraltma

Seccomp, konteyner sürecinin Linux çekirdeğine yapabildiği sistem çağrılarını filtreler. Docker'ın varsayılan profili izin listesi yaklaşımı kullanır ve yüzlerce sistem çağrısı içinden yaklaşık 44 riskli çağrıyı engeller. Docker, uyumluluğu koruyan bu varsayılan profil yerine `seccomp=unconfined` kullanılmasını önermiyor.

Varsayılan profili korumak için çoğu zaman ek ayar gerekmez. Özel profil yalnız ölçülen gereksinim varsa tanımlanmalıdır:

CODE TERMINAL
docker run --rm \
  --security-opt seccomp=/etc/docker/seccomp/app.json \
  registry.example/app:1.4.2


Özel profil yazarken izlenecek güvenli süreç:


  1. Önce Docker varsayılan profiliyle uygulamayı çalıştırın.
  2. Gerçek engellemeleri audit/log üzerinden ölçün; hata mesajından tahmin yürütmeyin.
  3. Bütün profili kapatmak yerine yalnız gereken syscall ve argümanı ekleyin.
  4. Profil dosyasını kod incelemesi, sürümleme ve bütünlük kontrolüne alın.
  5. Kernel ve Docker Engine güncellemesinden sonra regresyon testi çalıştırın.



`unconfined`, uygulama çalışsın diye kullanılan genel bir sorun giderme çözümü değildir. Filtreyi kapatmak, çekirdek saldırı yüzeyini gereksiz biçimde büyütür ve başka hardening katmanlarına daha fazla yük bindirir.

6. AppArmor veya SELinux: Dosya ve süreç davranışını sınırlama

Docker desteklenen sistemlerde varsayılan docker-default AppArmor profilini konteynerlere uygular. Özel profil; okunabilir/yazılabilir yolları, ağ yeteneklerini, sinyalleri, ptrace ve çalıştırılabilir dosyaları daha ayrıntılı sınırlayabilir.

AppArmor durumunu ve konteyner profilini kontrol edin:

CODE TERMINAL
sudo aa-status
docker inspect  \
  --format '{{.AppArmorProfile}}'


Özel profil kullanımı:

CODE TERMINAL
sudo apparmor_parser -r -W /etc/apparmor.d/containers/app-profile

docker run --rm \
  --security-opt apparmor=app-profile \
  registry.example/app:1.4.2


Önce complain/audit yaklaşımıyla meşru davranışı ölçüp sonra enforce moduna geçmek kesintiyi azaltır. Ancak uzun süre complain modunda bırakılan profil engelleme sağlamaz. SELinux kullanan dağıtımlarda aynı amaç type enforcement ve doğru volume label'larıyla sağlanır; AppArmor ve SELinux ayarlarını birbirine kopyalamayın.

7. Salt okunur root filesystem, tmpfs ve kontrollü volume

Uygulama çalışma anında kendi ikili dosyasını veya sistem dizinlerini değiştirmek zorunda olmamalıdır. Root filesystem'i salt okunur başlatın; gerçekten yazılması gereken geçici yolları tmpfs veya dar volume olarak açın:

CODE TERMINAL
docker run --rm \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,nodev,size=64m \
  --tmpfs /run:rw,nosuid,nodev,size=16m \
  --mount type=volume,src=app-data,dst=/app/data \
  registry.example/app:1.4.2


`noexec`, yorumlayıcı tarafından okunan her betiği sihirli biçimde engellemez; doğrudan çalıştırmayı kısıtlayan ek bir katmandır. Yazılabilir volume içine bırakılan dosyanın Node.js, Python, Java veya shell tarafından okunup yürütülebileceğini tehdit modelinde hesaba katın.

Bind mount gerekiyorsa ana sistem yolunu daraltın ve mümkünse salt okunur kullanın:

CODE TERMINAL
--mount type=bind,src=/srv/app/config,dst=/app/config,readonly


Ana sistem kökü, `/etc`, `/proc`, `/sys`, Docker veri dizini veya kullanıcı ev dizinini genel biçimde mount etmeyin. Volume sahipliği, yedekleme, şifreleme ve silme politikası da konteyner yaşam döngüsünden bağımsız yönetilmelidir.

8. Docker Compose için güvenli başlangıç şablonu

Aşağıdaki şablon bütün uygulamalara körlemesine uygulanacak nihai politika değildir; root olmayan süreç, capability azaltma, salt okunur kök, geçici dizin, kaynak limiti ve secret erişimi için başlangıç noktasıdır:

CODE TERMINAL
services:
  api:
    image: registry.example/app:1.4.2@sha256:
    user: "10001:10001"
    read_only: true
    init: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=64m
      - /run:rw,nosuid,nodev,size=16m
    pids_limit: 200
    mem_limit: 512m
    cpus: 1.0
    ports:
      - "127.0.0.1:8080:3000"
    networks:
      - frontend
    secrets:
      - db_password
    healthcheck:
      test: ["CMD", "node", "dist/healthcheck.js"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
    restart: unless-stopped

networks:
  frontend:
    driver: bridge

secrets:
  db_password:
    file: ./secrets/db_password.txt


Portun `127.0.0.1` adresine bağlanması, hizmeti doğrudan tüm ağ arayüzlerine açmaz; reverse proxy aynı ana sistemdeyse yararlıdır. Dağıtık ortamda ağ tasarımı değişir. `restart: unless-stopped` güvenlik kontrolü değil erişilebilirlik ayarıdır; sürekli çöküp yeniden başlayan servisi gizlememesi için alarm ve tekrar başlatma sayacı izlenmelidir.

Compose secrets Linux konteynerinde `/run/secrets/db_password` benzeri dosya olarak sunulur ve yalnız açıkça yetki verilen servise bağlanır. Bu mekanizma environment variable kullanımına göre kazara log/inspect sızıntısını azaltır. Yine de kaynak secret dosyasının ana sistem izinleri ve yedekleri korunmalıdır.

9. Kaynak limitleri: Güvenlik yalnız gizlilik değildir

Docker belgelerine göre varsayılan bir konteynerin CPU ve bellek limiti yoktur. Hatalı döngü, fork bomb, aşırı önbellek veya saldırı ana sistem kaynaklarını tüketebilir.

CODE TERMINAL
docker run --rm \
  --memory 512m \
  --memory-swap 512m \
  --cpus 1.0 \
  --pids-limit 200 \
  registry.example/app:1.4.2


Limitler tahminle değil yük testiyle belirlenmelidir. Çok düşük bellek uygulamayı OOM ile öldürür; çok yüksek sınır ise ana sistemi korumaz. Aşağıdaki göstergeleri izleyin:


  • OOMKilled durumu ve yeniden başlatma sayısı
  • Bellek working set ve limit oranı
  • CPU throttling süresi
  • PID sayısı ve pids limitine yaklaşma
  • Yazılabilir layer büyümesi
  • Log üretim hızı ve disk doluluk oranı



`--oom-kill-disable` seçeneğini bellek sınırı olmadan kullanmak ana sistemi riske atabilir. Docker'ın daemon'u koruyan OOM öncelik ayarını rastgele değiştirmeyin.

10. Ağ yüzeyini en aza indirme

Her servisi varsayılan geniş ağa koymak yerine kullanıcı tanımlı ağlarla iletişimi ihtiyaca göre ayırın. Veritabanı portunu ana sisteme publish etmeyin; yalnız uygulama ağına açın. İnternete çıkış gerekmeyen servisin egress erişimini ağ güvenlik duvarı veya platform politikasıyla sınırlandırın.

CODE TERMINAL
services:
  web:
    networks: [frontend]

  api:
    networks: [frontend, backend]

  db:
    networks: [backend]
    expose:
      - "5432"

networks:
  frontend: {}
  backend:
    internal: true


`internal: true`, ilgili Compose ağının dış erişimini sınırlar; tek başına kurum çapında mikro segmentasyon veya DNS güvenliği sağlamaz. Host firewall, cloud security group, reverse proxy, TLS ve uygulama kimlik doğrulaması ayrı katmanlardır.

`--network host`, port yayınlama ve network namespace izolasyonunu atlar. Çok özel performans veya ağ aracı senaryosu dışında kullanılmamalı; kullanım gerekçesi ve telafi kontrolleri belgeye bağlanmalıdır.

11. Docker socket neden özel bir tehlike?

Docker daemon çoğu rootful kurulumda ana sistem üzerinde yüksek yetkiyle çalışır. `/var/run/docker.sock` dosyasını konteynere yazılabilir bağlayan uygulama, daemon API'si üzerinden yeni konteyner oluşturabilir, ana sistem dizinlerini mount edebilir veya başka konteynerleri etkileyebilir.

Salt okunur socket mount çoğu durumda yeterli koruma değildir; API'nin bazı çağrıları HTTP yöntemi ve daemon davranışı üzerinden değişiklik yapabilir, ayrıca bilgi sızıntısı yaratır. “Docker'ı yöneten” CI/otomasyon bileşeni gerekiyorsa:


  • Ayrı ve güven sınırı belirlenmiş worker kullanın.
  • Gereken API işlemlerini izin listesine alan proxy veya aracı katman uygulayın.
  • Daemon'u herkese açık TCP soketinde kimlik doğrulamasız dinletmeyin.
  • mTLS, ağ erişim kontrolü, kısa ömürlü kimlik ve ayrıntılı denetim kaydı kullanın.
  • Uygulama iş yükü ile yönetim düzlemini aynı konteynerde birleştirmeyin.



12. İmaj tarama, imza ve yeniden oluşturma

Bir CVE taraması yalnız o anki veri tabanını ve paket envanterini yansıtır. “0 kritik” sonucu, uygulama kodunun güvenli olduğu veya yarın yeni CVE çıkmayacağı anlamına gelmez. Güçlü akış:


  1. Güvenilir ve küçük base image seçin.
  2. Tag yanında digest sabitleyin.
  3. SBOM üretin ve saklayın.
  4. İmajı bağımlılık/CVE taramasından geçirin.
  5. İmajı üretim pipeline'ında imzalayın ve provenance kaydı üretin.
  6. Registry ve dağıtım aşamasında imza/politika doğrulayın.
  7. Yeni CVE veya base image güncellemesinde imajı yeniden oluşturun; çalışan konteynere elle paket kurmayın.



İmajlar değişmez artefakt olarak ele alınmalıdır. Canlı konteynere `docker exec` ile girip paket güncellemek geçici ve izlenmesi zor bir durum yaratır. Düzeltme Dockerfile/bağımlılık tanımına işlenmeli, yeni imaj oluşturulmalı, test edilmeli ve kontrollü dağıtılmalıdır.

13. Üretim öncesi negatif güvenlik testleri

Hardening yalnız yapılandırma dosyasına bakılarak doğrulanmaz. Konteyner içinde beklenen başarısızlıkları test edin:

CODE TERMINAL
# Kimlik ve capabilities
id
grep '^Cap' /proc/self/status

# Kök dosya sistemine yazma başarısız olmalı
touch /should-fail

# İzin verilen geçici dizin çalışmalı
touch /tmp/expected-success

# Süreç ve mount görünürlüğünü incele
ps -ef
mount

# Konteyner dışından güvenlik ayarlarını doğrula
docker inspect  --format '{{json .HostConfig}}'


Test hedefleri:


  • Süreç UID 0 değil.
  • Effective capabilities beklenen minimum küme.
  • NoNewPrivileges etkin.
  • ReadonlyRootfs true.
  • Privileged false.
  • PidMode, IpcMode ve NetworkMode gerekçesiz host değil.
  • SecurityOpt seccomp/AppArmor/SELinux'i unconfined yapmıyor.
  • Mount listesinde Docker socket veya geniş ana sistem yolu yok.
  • Memory, NanoCpus/CPU ve PidsLimit değerleri sıfır/sınırsız değil.
  • Secret yalnız gerekli serviste ve doğru dosya izinleriyle okunabiliyor.



Uygulama başlangıçta başarısızsa ilk refleks `--privileged` veya `seccomp=unconfined` eklemek olmamalıdır. Hangi syscall, dosya yolu, capability veya port gereksiniminin eksik olduğu ölçülmeli ve yalnız o ihtiyaç açılmalıdır.

14. Olay müdahalesi ve adli iz

Konteynerde şüpheli faaliyet görüldüğünde yeniden başlatmak veya silmek uçucu kanıtı yok edebilir. Kurumun prosedürüne göre önce şu veriler korunmalıdır:


  • İmaj digest'i, container ID, oluşturma ve başlatma zamanı
  • Docker inspect çıktısı, mount'lar, security options ve environment anahtar adları
  • Çalışan süreçler, ağ bağlantıları ve açık dosyalar
  • Konteyner logları ile daemon/journald kayıtları
  • Yazılabilir layer farkı ve volume zaman çizelgesi
  • Registry pull, CI build, imza ve deployment denetim kayıtları



Secret değerlerini olay kaydına kopyalamayın. Kimlik bilgisi sızıntısı ihtimali varsa güvenilir yönetim kanalından döndürün, ilgili oturumları iptal edin ve hangi servislerin aynı sırrı kullandığını belirleyin.

Ele geçirilmiş konteyneri aynı imaj ve aynı sırlarla yeniden başlatmak iyileştirme değildir. Kök nedeni düzeltin, temiz kaynaktan yeni digest üretin, ana sistem ve komşu konteynerlere sıçrama ihtimalini inceleyin, ardından doğrulanmış imajı dağıtın.

Docker hardening kontrol listesi


  1. Güvenilir, küçük ve digest ile sabitlenmiş base image kullanılıyor mu?
  2. Multi-stage build üretim imajından derleme araçlarını çıkarıyor mu?
  3. `.dockerignore` sırları ve gereksiz dosyaları context dışında tutuyor mu?
  4. Dockerfile sabit UID/GID'li root olmayan `USER` ile bitiyor mu?
  5. Runtime'da `cap_drop: ALL` ve ölçülmüş minimum `cap_add` var mı?
  6. `no-new-privileges` etkin mi?
  7. Varsayılan veya test edilmiş özel seccomp profili korunuyor mu?
  8. AppArmor/SELinux profili enforce ediliyor mu?
  9. Root filesystem salt okunur, yazılabilir yollar tmpfs/volume ile dar mı?
  10. Docker socket, host root ve riskli cihaz mount'ları yok mu?
  11. Host network/PID/IPC namespace kullanılmıyor mu?
  12. Secret değerleri Dockerfile, ENV, log ve imaj katmanlarında bulunmuyor mu?
  13. CPU, bellek ve PID limitleri yük testiyle belirlenmiş mi?
  14. Yalnız gerekli portlar gerekli arayüzlerde yayımlanıyor mu?
  15. İmaj SBOM, CVE, imza ve provenance politikasından geçiyor mu?
  16. Yeni CVE'de yeniden build ve kontrollü rollout süreci var mı?
  17. Runtime güvenlik seçenekleri `docker inspect` ile otomatik doğrulanıyor mu?



Sonuç

Docker güvenliğinin en etkili ilkesi varsayılan yetkiyi azaltmaktır. Root olmayan süreç, `cap_drop: ALL`, `no-new-privileges`, seccomp, AppArmor/SELinux, salt okunur dosya sistemi, dar ağ ve kaynak limitleri birlikte kullanıldığında uygulama açığının etkisi önemli ölçüde sınırlandırılabilir.

Rootless mode daemon riskini azaltan güçlü bir seçenek, userns-remap ise rootful kurulumlarda konteyner UID'lerini ana sistemde ayrıcalıksız aralığa eşleyen ayrı bir kontroldür. İkisi de riskli mount, Docker socket, `--privileged` veya gizli veriyi imaja gömme hatasını telafi etmez.

Güvenli üretim hattı; küçük ve sabitlenmiş imajı düzenli yeniden oluşturur, sırları katmanlardan ayırır, çalışma zamanı politikasını otomatik test eder ve sapmayı izler. Uygulama ancak bir güvenlik seçeneği kapatıldığında çalışıyorsa yapılacak iş seçeneği kalıcı kapatmak değil, gerçek teknik gereksinimi ölçüp en dar istisnayı tanımlamaktır.

Kaynaklar

TR Siber Ekibi Yazar · X
Kaynak bağlantısı ← Ana sayfaya dön