Docker-Container bieten Isolation, aber Sicherheit ist kein Automatismus. Diese Best Practices helfen, Container sicher zu betreiben.
Grundprinzipien
Least Privilege
Minimale Rechte:
- Nicht als root laufen
- Nur nötige Capabilities
- Read-only Dateisysteme wo möglich
- Minimale ImagesDefense in Depth
Mehrere Schutzebenen:
- Sichere Images
- Netzwerk-Isolation
- Ressourcen-Limits
- Host-HardeningSichere Images
Offizielle Images verwenden
# GUT: Offizielle Images
FROM nginx:alpine
FROM node:20-slim
# SCHLECHT: Unbekannte Quellen
FROM randomuser/nginx-customMinimale Base Images
# Alpine ist klein und hat weniger Angriffsfläche
FROM alpine:3.19
# Oder Distroless für noch weniger
FROM gcr.io/distroless/staticImage-Größen
| Base Image | Größe | Anmerkung | |------------|-------|-----------| | ubuntu | ~77 MB | Viele Pakete | | debian:slim | ~30 MB | Reduziert | | alpine | ~5 MB | Minimal | | distroless | ~2 MB | Nur Runtime |
Images scannen
# Mit Docker Scout
docker scout cves nginx:latest
# Mit Trivy
trivy image nginx:latest
# Mit Snyk
snyk container test nginx:latestFeste Tags verwenden
# GUT: Feste Version
FROM nginx:1.25.3-alpine
# SCHLECHT: Kann sich ändern
FROM nginx:latest
FROM nginx:alpineNicht als Root laufen
Im Dockerfile
FROM node:20-alpine
# Benutzer erstellen
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Arbeitsverzeichnis mit richtigen Rechten
WORKDIR /app
COPY --chown=appuser:appgroup . .
# Als Nicht-Root ausführen
USER appuser
CMD ["node", "app.js"]Zur Laufzeit
# Benutzer beim Start setzen
docker run --user 1000:1000 nginx
# Oder in docker-compose.yml
services:
app:
image: myapp
user: "1000:1000"Root verhindern
# Container mit Rootless Docker
dockerd-rootless-setuptool.sh install
# Oder root komplett blockieren
docker run --user nobody nginxCapabilities einschränken
Alle Capabilities entfernen
docker run --cap-drop=ALL nginxNur nötige hinzufügen
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginxIn Docker Compose
services:
web:
image: nginx
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICEWichtige Capabilities
| Capability | Bedeutung | Braucht wer? | |------------|-----------|--------------| | NET_BIND_SERVICE | Ports < 1024 | Webserver | | CHOWN | Besitzer ändern | Selten | | SETUID/SETGID | User wechseln | Selten | | SYS_ADMIN | Viele Rechte | Fast nie! |
Read-Only Dateisystem
Container read-only starten
docker run --read-only nginxMit tmpfs für temporäre Dateien
docker run --read-only \
--tmpfs /tmp \
--tmpfs /var/run \
nginxIn Docker Compose
services:
web:
image: nginx
read_only: true
tmpfs:
- /tmp
- /var/runNetzwerk-Sicherheit
Interne Netzwerke
# docker-compose.yml
services:
app:
networks:
- frontend
- backend
db:
networks:
- backend # Nur intern erreichbar!
networks:
frontend:
backend:
internal: true # Kein Internet-ZugangPorts nur lokal
# Nur auf localhost
docker run -p 127.0.0.1:3306:3306 mysql
# Statt
docker run -p 3306:3306 mysql # Auf allen IPs!Inter-Container-Kommunikation
# ICC deaktivieren (Docker-Daemon)
dockerd --icc=falseRessourcen-Limits
CPU und RAM begrenzen
docker run --memory=512m --cpus=1.0 nginxIn Docker Compose
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256MProzesse begrenzen
docker run --pids-limit=100 nginxSecrets sicher handhaben
NICHT: Secrets in Umgebungsvariablen
# SCHLECHT: Sichtbar in docker inspect
services:
app:
environment:
- DB_PASSWORD=geheim123Docker Secrets (Swarm)
# Secret erstellen
echo "mein-passwort" | docker secret create db_password -
# In Service verwenden
docker service create \
--secret db_password \
--env DB_PASSWORD_FILE=/run/secrets/db_password \
myappSecrets in Compose (Swarm Mode)
services:
app:
secrets:
- db_password
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txtAlternative: Externe Secret-Manager
# Mit HashiCorp Vault
services:
app:
environment:
- VAULT_ADDR=http://vault:8200
# App liest Secrets von VaultHost-Bindungen vermeiden
Gefährliche Mounts
# SEHR GEFÄHRLICH: Docker-Socket
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
# Erlaubt Container-Ausbruch!
# GEFÄHRLICH: Wichtige Host-Verzeichnisse
docker run -v /:/host ...Sichere Alternativen
# Nur nötige Verzeichnisse
docker run -v /app/data:/data:ro myapp # read-only wenn möglich
# Named Volumes statt Bind Mounts
docker run -v mydata:/data myappSecurity-Optionen
Seccomp-Profile
# Standard-Profil blockiert gefährliche Syscalls
docker run --security-opt seccomp=default.json nginx
# Eigenes Profil
docker run --security-opt seccomp=my-profile.json nginxAppArmor
# Mit AppArmor-Profil
docker run --security-opt apparmor=docker-default nginxNo New Privileges
# Verhindert Privilege Escalation
docker run --security-opt no-new-privileges nginxIn Docker Compose
services:
app:
security_opt:
- no-new-privileges:true
- seccomp:./seccomp-profile.jsonDocker-Daemon absichern
TLS aktivieren
// /etc/docker/daemon.json
{
"tls": true,
"tlscacert": "/etc/docker/ca.pem",
"tlscert": "/etc/docker/server-cert.pem",
"tlskey": "/etc/docker/server-key.pem",
"tlsverify": true
}Live-Restore aktivieren
{
"live-restore": true
}User Namespaces
{
"userns-remap": "default"
}Checkliste
□ Offizielle/minimale Base Images
□ Feste Image-Tags (keine :latest)
□ Images auf Vulnerabilities scannen
□ Nicht als root laufen
□ Capabilities einschränken
□ Read-only Dateisystem
□ Ressourcen-Limits setzen
□ Interne Netzwerke für Backend
□ Ports nur lokal binden
□ Secrets sicher handhaben
□ Keine Docker-Socket-Mounts
□ Security-Optionen (no-new-privileges)Scanning automatisieren
GitHub Actions
# .github/workflows/scan.yml
name: Container Scan
on: push
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
severity: 'HIGH,CRITICAL'
exit-code: '1'Fazit
Container-Sicherheit erfordert mehrere Maßnahmen: sichere Images, minimale Rechte, Netzwerk-Isolation und Ressourcen-Limits. Scannen Sie Images regelmäßig, vermeiden Sie root und schützen Sie Secrets. Die meisten Maßnahmen sind einfach umzusetzen und verbessern die Sicherheit erheblich.