Veröffentlicht am

Docker Administration: Security, Monitoring und Lifecycle

Teilen:
Authors

Docker Administration in der Praxis: Security, Monitoring und Lifecycle-Management

TL;DR

  • Docker-Daemon-Defaults sind fuer Entwicklung optimiert, nicht fuer Produktion -- die daemon.json muss angepasst werden
  • Container sollten immer als Non-Root laufen, mit Read-Only Filesystem und gedroppten Capabilities
  • Image-Groesse und Layer-Aufbau haben direkten Einfluss auf Startup-Zeit und Sicherheitsflaeche
  • Monitoring mit Prometheus und cAdvisor ist Pflicht, Logging mit strukturiertem JSON-Output und Log-Rotation
  • Regelmaessiges Aufraeumen von ungenutzten Images, Volumes und Netzwerken verhindert Disk-Probleme

Docker Daemon fuer Produktion konfigurieren

Die Standard-Installation von Docker ist fuer Entwickler gemacht. Fuer produktionsnahe Umgebungen muessen mehrere Defaults angepasst werden. Die zentrale Konfigurationsdatei ist /etc/docker/daemon.json:

{
  "storage-driver": "overlay2",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "5",
    "compress": "true"
  },
  "live-restore": true,
  "userland-proxy": false,
  "no-new-privileges": true,
  "icc": false,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65536,
      "Soft": 65536
    }
  },
  "default-address-pools": [
    {
      "base": "172.20.0.0/16",
      "size": 24
    }
  ]
}

Die wichtigsten Einstellungen erklaert:

EinstellungWarumDefault
live-restore: trueContainer laufen weiter, wenn der Daemon neustartetfalse
icc: falseContainer koennen sich nicht gegenseitig erreichen, ausser explizit verlinkttrue
no-new-privileges: trueProzesse im Container koennen keine neuen Privilegien erlangenfalse
userland-proxy: falseNutzt iptables statt userland proxy -- besser fuer Performancetrue
log-opts.max-sizeVerhindert, dass Logs die Disk fuellenUnbegrenzt

Nach der Aenderung: sudo systemctl restart docker. Wenn live-restore bereits aktiv war, laufen bestehende Container weiter.

Container-Security: Die wichtigsten Massnahmen

Ein unsicherer Container-Start sieht so aus: docker run -d nginx. Kein User gesetzt, alle Capabilities aktiv, beschreibbares Filesystem. In Produktion sollte das so aussehen:

docker run -d \
  --name web \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  --tmpfs /var/cache/nginx:rw,noexec,nosuid,size=32m \
  --security-opt no-new-privileges:true \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --user 101:101 \
  --memory 256m \
  --cpus 0.5 \
  --pids-limit 50 \
  --restart unless-stopped \
  --health-cmd "wget -q --spider http://localhost/ || exit 1" \
  --health-interval 30s \
  --health-timeout 5s \
  --health-retries 3 \
  nginx:1.27-alpine

Was hier passiert:

  • --read-only: Filesystem ist nicht beschreibbar. Angreifer koennen nichts persistieren.
  • --tmpfs: Nur bestimmte Verzeichnisse sind beschreibbar, mit Groessenlimit.
  • --cap-drop ALL --cap-add NET_BIND_SERVICE: Nur die Capability, die nginx braucht (Port 80 binden).
  • --user 101:101: nginx-User statt Root.
  • --pids-limit 50: Fork-Bombs werden begrenzt.

Fuer automatisiertes Vulnerability-Scanning empfehle ich Trivy:

# Image vor dem Deployment scannen
trivy image --severity HIGH,CRITICAL nginx:1.27-alpine

# Ergebnis als JSON fuer CI/CD-Integration
trivy image --format json --output results.json nginx:1.27-alpine

# Im CI: Build abbrechen bei CRITICAL Findings
trivy image --exit-code 1 --severity CRITICAL myapp:latest

Multi-Stage Builds: Kleine, sichere Images

Grosse Images sind ein Security- und Performance-Problem. Jedes zusaetzliche Package ist eine potenzielle Schwachstelle. Multi-Stage Builds trennen Build-Dependencies von der Runtime:

# Stage 1: Build
FROM golang:1.22-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app

# Stage 2: Runtime
FROM scratch
COPY --from=build /app /app
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
USER 65534:65534
ENTRYPOINT ["/app"]

Der Unterschied ist enorm:

VarianteImage-GroesseCVEs (typisch)
golang:1.22 (full)~850 MB50-100+
golang:1.22-alpine~250 MB5-20
Multi-Stage (scratch)~10 MB0

Das scratch-Image enthaelt buchstaeblich nichts -- kein Shell, kein Package Manager, keine Libraries. Angreifer haben nichts, womit sie arbeiten koennen.

Docker Compose fuer strukturierte Deployments

Fuer Umgebungen, die noch nicht Kubernetes nutzen (oder fuer lokale Development-Setups), ist Docker Compose das richtige Werkzeug. Ein Beispiel fuer eine typische Web-App mit Datenbank und Reverse Proxy:

services:
  proxy:
    image: nginx:1.27-alpine
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      app:
        condition: service_healthy
    networks:
      - frontend
    deploy:
      resources:
        limits:
          memory: 128M
          cpus: "0.25"
    read_only: true
    tmpfs:
      - /tmp
      - /var/cache/nginx

  app:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - DATABASE_URL=postgresql://app:${DB_PASSWORD}@db:5432/appdb
      - LOG_LEVEL=info
    networks:
      - frontend
      - backend
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 10s
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "1.0"
    read_only: true
    tmpfs:
      - /tmp
    user: "1000:1000"

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  pgdata:

Wichtige Punkte: Das backend-Netzwerk ist internal: true -- kein direkter Internetzugang fuer die Datenbank. Passwort kommt aus einer .env-Datei, nicht hardcoded. Health Checks stellen sicher, dass proxy erst startet, wenn app bereit ist.

Monitoring und Logging

Ohne Monitoring sieht man Probleme erst, wenn sie in Produktion eskalieren. Das Minimum fuer Docker-Hosts:

Metriken mit Prometheus + cAdvisor:

# cAdvisor starten (sammelt Container-Metriken)
docker run -d \
  --name cadvisor \
  --volume /:/rootfs:ro \
  --volume /var/run:/var/run:ro \
  --volume /sys:/sys:ro \
  --volume /var/lib/docker/:/var/lib/docker:ro \
  --publish 8080:8080 \
  gcr.io/cadvisor/cadvisor:v0.49.1

# Prometheus scrape config
# prometheus.yml
# scrape_configs:
#   - job_name: cadvisor
#     static_configs:
#       - targets: ["cadvisor:8080"]

Logging: JSON-Output und Log-Rotation.

Container sollten nach stdout/stderr loggen. Docker faengt das ab und speichert es. Ohne max-size in der daemon.json wachsen Log-Dateien unbegrenzt. Das fuehrt frueher oder spaeter zu vollen Disks.

# Log-Groesse eines Containers pruefen
docker inspect --format='{{.LogPath}}' <container> | xargs ls -lh

# Alle Container-Logs: Gesamtgroesse
du -sh /var/lib/docker/containers/*/

Regelmaessige Wartung: Disk-Platz zurueckgewinnen

Docker raeumt nichts automatisch auf. Ueber Wochen und Monate sammeln sich ungenutzte Images, gestoppte Container und verwaiste Volumes:

# Ueberblick: Wie viel Platz nutzt Docker?
docker system df

# Alles aufraeumen, was nicht aktiv genutzt wird
docker system prune -a --volumes

# Weniger aggressiv: Nur Images ohne Tag und gestoppte Container
docker image prune
docker container prune

# Regelmaessig per Cron (z.B. wochentlich)
# /etc/cron.weekly/docker-cleanup
docker image prune -a --filter "until=168h" --force
docker volume prune --force
docker network prune --force

Wichtig: docker system prune -a --volumes loescht auch ungenutzte Named Volumes. Fuer Produktion lieber gezielt aufraeumen.

Backup-Strategie fuer Docker Volumes

Volumes enthalten den persistenten State. Ohne Backup-Strategie ist ein Datenverlust nur eine Frage der Zeit:

#!/bin/bash
# docker-volume-backup.sh

BACKUP_DIR="/opt/backups/docker"
DATE=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=14

mkdir -p "$BACKUP_DIR"

# Alle Volumes mit Label "backup=true" sichern
for volume in $(docker volume ls -q --filter label=backup=true); do
  echo "Backup: $volume"
  docker run --rm \
    -v "$volume":/source:ro \
    -v "$BACKUP_DIR":/backup \
    alpine tar czf "/backup/${volume}_${DATE}.tar.gz" -C /source .
done

# Alte Backups aufraeumen
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete

echo "Backup abgeschlossen: $(ls -1 $BACKUP_DIR/*_${DATE}.tar.gz | wc -l) Volumes gesichert"

Wann von Docker zu Kubernetes wechseln?

Docker Compose und Docker Swarm haben ihre Berechtigung. Aber ab einem bestimmten Punkt stossen sie an Grenzen:

KriteriumDocker (Compose/Swarm)Kubernetes
Anzahl ContainerBis ~5050+
Teams1-23+
Auto-ScalingManuell/Swarm basicHPA, VPA, Karpenter
Service DiscoveryDocker DNSCoreDNS, Service Mesh
Rolling UpdatesBasis-SupportFeingranular steuerbar
Secrets ManagementDocker SecretsSecrets, External Secrets, Vault
Self-HealingRestart PoliciesPod-Rescheduling, Liveness Probes
EcosystemBegrenztRiesig (Operators, CRDs)

Der Wechsel zu Kubernetes lohnt sich, wenn die Komplexitaet der Docker-Workarounds die Komplexitaet von Kubernetes uebersteigt. Das passiert typischerweise bei 3+ Teams oder 50+ Containern.

Verwandte Artikel

Fazit

Docker-Administration ist mehr als docker run. Ein produktionsreifes Setup braucht gehaeertete Daemon-Konfiguration, Security-Defaults in jedem Container, strukturiertes Monitoring und regelmaessige Wartung.

Die gute Nachricht: Die meisten Massnahmen sind einmalig einzurichten und danach wartungsarm. Die daemon.json aendern, eine CI-Pipeline mit Trivy aufsetzen, cAdvisor deployen -- das sind ein paar Stunden Arbeit, die sich langfristig auszahlen.

Wenn Sie Unterstuetzung bei der Docker-Administration oder dem Umstieg auf Kubernetes brauchen, erreichen Sie uns unter /kontakt.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen