Zum Hauptinhalt springen
Zurück zur Kategorie

Docker-Sicherheit: Container-Umgebung absichern

Docker-Sicherheits-Best-Practices: Nicht-Root-Benutzer, Read-Only-Dateisystem, Seccomp-Profile, Image-Scanning, Docker-Socket-Sicherheit, Netzwerkisolierung und Secrets-Verwaltung.

Lesezeit: 17 dk Container & Orchestrierung
dockersicherheitcontainerseccompapparmorimage-scanningsecretshärtung

Inhaltsverzeichnis

Docker-Sicherheit: Container-Umgebung absichern

Docker-Container können in ihrer Standardkonfiguration viele Sicherheitslücken aufweisen. Container, die als Root laufen, überprivilegierte Container und unsichere Images stellen ernsthafte Risiken dar. In diesem Leitfaden behandeln wir Docker-Sicherheit Schicht für Schicht.

1. Als Nicht-Root-Benutzer ausführen

Die grundlegendste Sicherheitsmaßnahme: Container als Nicht-Root-Benutzer ausführen.

Benutzer im Dockerfile definieren

hljs dockerfile
# Schlechte Praxis — als Root ausführen
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]

# Gute Praxis — Nicht-Root-Benutzer
FROM node:20

# Benutzer und Gruppe erstellen
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

WORKDIR /app
COPY --chown=appuser:appgroup . .
RUN npm ci --only=production

# Zu Nicht-Root-Benutzer wechseln
USER appuser

CMD ["node", "server.js"]

Benutzer zur Laufzeit angeben

hljs bash
# Mit bestimmtem Benutzer ausführen
docker run -d --user 1000:1000 myapp:latest

# Mit aktuellem Benutzer ausführen
docker run -d --user $(id -u):$(id -g) myapp:latest

2. Read-Only-Dateisystem

hljs bash
# Mit Read-Only-Root-Dateisystem ausführen
docker run -d \
  --name myapp \
  --read-only \
  --tmpfs /tmp \
  --tmpfs /var/run \
  myapp:latest
hljs yaml
# docker-compose.yml
services:
  app:
    image: myapp:latest
    read_only: true
    tmpfs:
      - /tmp
      - /var/run
    volumes:
      - app-logs:/app/logs

3. Capability-Verwaltung

hljs bash
# Alle Capabilities entfernen, nur benötigte hinzufügen
docker run -d \
  --name myapp \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  myapp:latest

# NIEMALS privilegierten Modus verwenden
# docker run --privileged myapp  # SCHLECHTE PRAXIS
hljs yaml
services:
  app:
    image: myapp:latest
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
      - CHOWN

4. Seccomp-Profile

hljs bash
# Mit Standard-Seccomp-Profil ausführen (empfohlen)
docker run -d --security-opt seccomp=default myapp:latest

# Benutzerdefiniertes Seccomp-Profil
docker run -d \
  --security-opt seccomp=/path/to/seccomp-profile.json \
  myapp:latest

5. Docker-Image-Sicherheit

Sichere Dockerfile-Praktiken

hljs dockerfile
# Minimales Image mit Multi-Stage-Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Produktions-Image — minimal
FROM node:20-alpine

# Sicherheitsupdates anwenden
RUN apk update && apk upgrade && apk add --no-cache dumb-init

# Nicht-Root-Benutzer
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules

USER appuser

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]

Image-Scanning

hljs bash
# Mit Trivy scannen (empfohlen)
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image myapp:latest

# Nur kritische und hohe Schweregrade
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest image \
  --severity CRITICAL,HIGH \
  myapp:latest

6. Docker-Socket-Sicherheit

hljs bash
# Docker-Socket schreibgeschützt einbinden (für Monitoring)
docker run -d \
  --name monitoring \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  monitoring-app:latest

# Docker-Socket NIEMALS in Produktions-Containern einbinden!

7. Secrets-Verwaltung

hljs bash
# Docker-Secret verwenden (Swarm-Modus)
echo "StarkesPasswort123!" | docker secret create db_password -

docker service create \
  --name myapp \
  --secret db_password \
  myapp:latest
# Secret zugänglich unter /run/secrets/db_password

8. Netzwerksicherheit

hljs bash
# Nur notwendige Ports exponieren
docker run -d \
  --name myapp \
  -p 127.0.0.1:8080:8080 \
  myapp:latest

9. Ressourcenlimits

hljs bash
# CPU- und Speicherlimits
docker run -d \
  --name myapp \
  --memory 512m \
  --memory-swap 512m \
  --cpus 1.0 \
  --pids-limit 100 \
  myapp:latest

10. Docker-Daemon-Sicherheit

hljs json
// /etc/docker/daemon.json
{
  "icc": false,
  "no-new-privileges": true,
  "userns-remap": "default",
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Fazit

Docker-Sicherheit erfordert einen mehrschichtigen Ansatz. Beginnen Sie mit Nicht-Root-Benutzer, Read-Only-Dateisystem, minimalen Capabilities und Image-Scanning. Übergeben Sie Secrets niemals als Umgebungsvariablen, binden Sie den Docker-Socket nicht unnötig ein und schützen Sie sich mit Ressourcenlimits vor DoS-Angriffen. Mit diesen Sicherheitsmaßnahmen auf REXE-Servern können Sie Ihre Container-Infrastruktur sicher halten.