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ırma | Risk | Güvenli yaklaşım |
|---|---|---|
| --privileged | Neredeyse tüm cihaz ve kernel yetkilerini açar | Kullanmayın; gereken tek capability veya device erişimini belirleyin |
| /var/run/docker.sock mount | Konteynerden Docker daemon kontrolü sağlayabilir | Soketi uygulama konteynerine bağlamayın; dar yetkili aracı katman kullanın |
| --network host | Ağ namespace ayrımını kaldırır | Kullanıcı tanımlı bridge ağı ve yalnız gerekli port yayını |
| --pid host / --ipc host | Ana sistem süreç/IPC yüzeyini açar | Varsayılan ayrı namespace'leri koruyun |
| cap_add: ALL | Kök yetkisini genişletir | cap_drop: ALL; yalnız ölçülen tekil ihtiyaçları ekleyin |
| seccomp=unconfined | Sistem çağrısı filtresini kapatır | Docker'ın varsayılan seccomp profilini koruyun |
| apparmor=unconfined | LSM dosya/işlem sınırlarını kaldırır | docker-default veya test edilmiş özel profil |
| /:/host gibi bind mount | Ana dosya sistemine yazma erişimi verir | Dar yol, read_only mount ve sahiplik kontrolü |
| Sınırsız bellek/PID | Hizmet reddi ve ana sistem kararsızlığı | memory, cpus ve pids_limit tanımlayın |
| İmajda/env'de sır | Katman, 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*.ymlListe 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 ciCODE 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.
| Özellik | Rootless mode | userns-remap |
|---|---|---|
| Docker daemon | Root olmayan kullanıcı | Root |
| Konteyner kimliği | User namespace içinde eşlenir | Ana sistemde subordinate UID/GID aralığına eşlenir |
| Daemon açığının etkisi | Daha dar ayrıcalık hedeflenir | Root daemon riski devam eder |
| Uyumluluk | Ağ, cgroup, düşük port ve depolama sınırlamaları olabilir | Bind mount sahipliği ve mevcut volume geçişi dikkat ister |
| Kullanım | Uyumlu genel iş yüklerinde güçlü varsayılan | Rootful 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.2Uygulama 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ç:
- Önce Docker varsayılan profiliyle uygulamayı çalıştırın.
- Gerçek engellemeleri audit/log üzerinden ölçün; hata mesajından tahmin yürütmeyin.
- Bütün profili kapatmak yerine yalnız gereken syscall ve argümanı ekleyin.
- Profil dosyasını kod incelemesi, sürümleme ve bütünlük kontrolüne alın.
- 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,readonlyAna 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.txtPortun `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.2Limitler 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ış:
- Güvenilir ve küçük base image seçin.
- Tag yanında digest sabitleyin.
- SBOM üretin ve saklayın.
- İmajı bağımlılık/CVE taramasından geçirin.
- İmajı üretim pipeline'ında imzalayın ve provenance kaydı üretin.
- Registry ve dağıtım aşamasında imza/politika doğrulayın.
- 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
- Güvenilir, küçük ve digest ile sabitlenmiş base image kullanılıyor mu?
- Multi-stage build üretim imajından derleme araçlarını çıkarıyor mu?
- `.dockerignore` sırları ve gereksiz dosyaları context dışında tutuyor mu?
- Dockerfile sabit UID/GID'li root olmayan `USER` ile bitiyor mu?
- Runtime'da `cap_drop: ALL` ve ölçülmüş minimum `cap_add` var mı?
- `no-new-privileges` etkin mi?
- Varsayılan veya test edilmiş özel seccomp profili korunuyor mu?
- AppArmor/SELinux profili enforce ediliyor mu?
- Root filesystem salt okunur, yazılabilir yollar tmpfs/volume ile dar mı?
- Docker socket, host root ve riskli cihaz mount'ları yok mu?
- Host network/PID/IPC namespace kullanılmıyor mu?
- Secret değerleri Dockerfile, ENV, log ve imaj katmanlarında bulunmuyor mu?
- CPU, bellek ve PID limitleri yük testiyle belirlenmiş mi?
- Yalnız gerekli portlar gerekli arayüzlerde yayımlanıyor mu?
- İmaj SBOM, CVE, imza ve provenance politikasından geçiyor mu?
- Yeni CVE'de yeniden build ve kontrollü rollout süreci var mı?
- 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
- Docker Docs – Docker Engine security
- Docker Docs – Rootless mode
- Docker Docs – User namespace remapping
- Docker Docs – Seccomp security profiles
- Docker Docs – AppArmor security profiles
- Docker Docs – Resource constraints
- Docker Docs – Building best practices
- Docker Docs – Build secrets
- Docker Docs – Docker Compose secrets
- Docker Docs – Running containers
TR Siber Ekibi