Docker Güvenliği (Container Hardening) 🐳
Senin yaşadığın senaryo tam olarak buydu:
RCE Açığı → Root Container → Tam Sistem Erişimi → Cryptominer/DDoS → 💀
İşte bu zinciri kırmak için kapsamlı Docker güvenlik rehberi.
1. ASLA Root Olarak Çalıştırma (En Kritik!) �
Varsayılan olarak Docker konteynerleri root yetkisiyle çalışır. Konteynerden kaçan biri host makinede de root olur!
Çözüm 1: Dockerfile'da USER Tanımla (En İyisi)
# ✅ DOĞRU Dockerfile
FROM node:18-alpine
# Sistem kullanıcısı oluştur (UID: 1001)
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
WORKDIR /app
COPY --chown=appuser:appgroup . .
# Root'tan çık
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
Çözüm 2: Docker Compose'da Zorla
2. Read-Only Filesystem (Dosya Yazmayı Kapat) 📁
Saldırgan içeri girse bile dosya yazamasın, malware indiremesin.
services:
app:
image: my-app
read_only: true
tmpfs:
- /tmp:size=100M,mode=1777
- /var/run:size=50M
volumes:
- ./data:/app/data:rw # Sadece gerekli yere yazma izni
3. Resource Limitleri (Miner Koruması) ⚡
CPU %100'e dayamasın, RAM tüketmesin.
services:
app:
image: my-app
deploy:
resources:
limits:
cpus: "0.5" # Max yarım işlemci
memory: 512M # Max 512MB RAM
reservations:
cpus: "0.25"
memory: 256M
pids_limit: 100 # Fork bomb koruması
mem_swappiness: 0 # Swap yasak
4. Network İzolasyonu 🌐
Konteynerler dışarıya kafasına göre çıkamasın.
services:
backend:
image: my-api
networks:
- internal-net # Sadece bu ağdaki veritabanına erişebilir
networks:
internal-net:
driver: bridge
internal: true # Dış dünyaya (İnternete) erişim YOK!
Not:
network_mode: hostkullanmak yasaktır!
5. Capabilities & Privileges 🔐
Docker'ın "ben her şeyi yaparım" yetkilerini tırpanlayın.
services:
app:
cap_drop:
- ALL # Önce her şeyi kapat
cap_add:
- NET_BIND_SERVICE # Sadece port açabilsin
security_opt:
- no-new-privileges:true # Privilege escalation (yetki yükseltme) engelle
Tehlikeli Alanlar ⛔
--privileged: ASLA kullanma! Host makinenin tüm cihazlarına erişim verir./var/run/docker.sock: Mount etme! Konteynerin diğer konteynerleri silmesine/yaratmasına izin verir.
6. Secrets Yönetimi (Şifre Saklama) 🔑
Environment değişkenleri (-e PASSWORD=123) docker inspect ile görülebilir. Docker Secrets kullanın.
services:
db:
image: postgres
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
7. Komple Güvenli docker-compose.yml Örneği 🏆
Bunu kopyala ve projelerinde şablon olarak kullan:
version: "3.8"
services:
app:
image: my-app:latest
# 1. Non-root user
user: "1001:1001"
# 2. Read-only filesystem
read_only: true
tmpfs:
- /tmp:size=100M,mode=1777
# 3. Resource limits
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
pids_limit: 100
# 4. Capabilities
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
# 5. Network isolation
networks:
- frontend
# 6. Secrets
secrets:
- api_key
# 7. Logging limiti (Diski doldurmasın)
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# 8. Health check (Zombie container tespiti & Auto-restart)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
frontend:
driver: bridge
secrets:
api_key:
file: ./secrets/api_key.txt
8. Güvenlik Kontrol Scripti �
Mevcut konteynerlerin ne kadar güvenli? Bu script ile tara:
Dosya: docker_security_check.sh
#!/bin/bash
echo "=== 🐳 DOCKER GÜVENLİK KONTROLÜ ==="
echo -e "\n[1] Root olarak çalışan container'lar:"
for c in $(docker ps -q); do
USER=$(docker exec $c whoami 2>/dev/null || echo "N/A")
NAME=$(docker inspect --format '{{.Name}}' $c)
if [ "$USER" = "root" ]; then
echo " ⚠️ $NAME: ROOT! (Düzeltilmeli)"
else
echo " ✅ $NAME: $USER"
fi
done
echo -e "\n[2] Privileged container'lar:"
docker ps -q | xargs docker inspect --format '{{.Name}}: Privileged={{.HostConfig.Privileged}}' | grep "true" || echo " ✅ Yok"
echo -e "\n[3] Docker socket mount edilmiş:"
docker ps -q | xargs docker inspect --format '{{.Name}}: {{.Mounts}}' | grep "docker.sock" || echo " ✅ Yok"
echo -e "\n[4] Resource limiti OLMAYAN container'lar:"
for c in $(docker ps -q); do
NAME=$(docker inspect --format '{{.Name}}' $c)
MEM=$(docker inspect --format '{{.HostConfig.Memory}}' $c)
if [ "$MEM" = "0" ]; then
echo " ⚠️ $NAME: Limit yok! (Riskli)"
fi
done
echo -e "\n[5] Host network kullananlar:"
docker ps -q | xargs docker inspect --format '{{.Name}}: {{.HostConfig.NetworkMode}}' | grep "host" || echo " ✅ Yok"
echo -e "\n=== KONTROL TAMAMLANDI ==="
Scripti Çalıştırma
# Scripti kaydet ve çalıştırılabilir yap
sudo nano /usr/local/bin/docker_security_check.sh
# (Yukarıdaki içeriği yapıştır)
sudo chmod +x /usr/local/bin/docker_security_check.sh
# Çalıştır
docker_security_check.sh
9. Image Güvenliği 🖼️
Container'ların temeli olan image'lar güvenli değilse, üstüne ne yaparsanız yapın boştur.
Güvenilir Image Kullan
# ❌ YANLIŞ: Random kullanıcı image'ı (İçinde ne olduğu belirsiz)
docker pull randomuser/nginx-super
# ✅ DOĞRU: Official veya Verified Publisher
docker pull nginx:alpine
docker pull bitnami/nginx
Minimal Base Image (Alpine Tercih Et)
# ❌ Büyük image = Daha fazla güvenlik açığı, daha yavaş
FROM node:18 # ~900MB, yüzlerce gereksiz paket
# ✅ Minimal image = Küçük attack surface, hızlı
FROM node:18-alpine # ~100MB, sadece gerekli paketler
Image Tarama (Trivy)
Image'ı production'a almadan önce mutlaka tarayın.
# Kurulum
sudo apt install trivy -y
# Image tara
trivy image nginx:latest
trivy image my-app:latest
# CI/CD'de: HIGH/CRITICAL varsa build'i durdur
trivy image --exit-code 1 --severity HIGH,CRITICAL my-app:latest
10. Docker Daemon Hardening 🔧
Docker servisini (Daemon) güvenli hale getirmek için /etc/docker/daemon.json dosyasını yapılandırın.
Dosya: /etc/docker/daemon.json
{
"icc": false,
"userns-remap": "default",
"no-new-privileges": true,
"live-restore": true,
"userland-proxy": false,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Uygula:
| Ayar | Açıklama |
|---|---|
icc: false |
Container'lar arası varsayılan iletişimi kapat (Herkes herkesle konuşamaz). |
userns-remap |
Container root ≠ Host root (İzolasyon). |
no-new-privileges |
Privilege escalation engelle. |
live-restore |
Docker restart olunca container'lar ölmesin. |
log-driver |
Logların diski doldurmasını engelle (Log Rotation). |
Özet: Saldırı vs Önlem 🛡️
| Saldırı Tipi | Önlem |
|---|---|
| Container Breakout | Non-root User, Read-only FS, No-Privileges |
| Crypto Mining | Resource Limits (CPU/RAM) |
| DDoS / Scanning | Internal Network (İzolasyon) |
| Data Theft | Docker Secrets |