// Tutorial · Debian · Container

Debian 13 (Trixie): Container absichern & automatisiert betreiben (Teil 5)

📅 06.09.2026 ⏱15 Min. Lesezeit ✍️ Redaktion

Server gehärtet, Firewall steht, Backups laufen – jetzt kommen die Dienste. Teil 5 zeigt, wie du Docker-Container auf deinem Debian-13-Server sicher betreibst: Images, Rechte, Secrets, Updates und Stack-Backups im Zusammenspiel mit der Blog-Serie.

Warum Container-Härtung?

Mit Teil 1–4 ist der Host vorbereitet: Basis, Härtung, Firewall, Monitoring und Backups. In Teil 5 geht es um die eigentlichen Arbeitspferde – deine Container. Ein Container ist keine Sicherheitsgrenze an sich: Ohne Limits, Read-only-Dateisystem und saubere Rechtevergabe ist er nur ein bequemer Weg, Software auszuführen. Mit dem Grundgerüst aus diesem Artikel betreibst du Stacks, die den Härtungs-Standard aus Teil 2 und 3 fortsetzen.

Passend zur Serie: Die Beispiele greifen die Blog-Artikel auf – Watchtower, Uptime Kuma, Podman vs. Docker und Duplicati. Teil 5 bündelt sie für den Debian-Host.

Konzept: Isolation, Least Privilege, Automatisierung

Drei Grundsätze bestimmen den sicheren Container-Betrieb:

  • Isolation: Jeder Dienst bekommt eigene Limits – CPU, RAM, Prozesse, Dateisystem.
  • Least Privilege: Nur die Rechte, die der Dienst wirklich braucht – keine Root-Capabilities, kein Schreibzugriff, wo Lesen reicht.
  • Automatisierung: Updates, Neustarts und Backups laufen geplant – nicht wenn du zufällig dran denkst.

Der Rest des Artikels setzt diese drei Punkte in konkrete Dateien und Befehle um.

Docker auf dem gehärteten Server installieren

Debian liefert docker.io mit, die offiziellen Pakete sind aber aktueller. Empfohlener Weg über das offizielle Docker-Repository:

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian trixie stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable --now docker
Warnung – docker-Gruppe: Wer der Gruppe docker angehört, hat faktisch Root-Rechte auf dem Host. Mitglieder nur aufnehmen, wenn es wirklich nötig ist – die saubere Alternative ist Rootless (Ausblick in Teil 6).

Container härten: Das sichere Compose-Grundgerüst

Dieses Grundgerüst lässt sich auf fast jeden Dienst aus der Blog-Serie übertragen:

services:
  app:
    image: beispiel/app:latest
    restart: unless-stopped
    read_only: true
    tmpfs:
      - /tmp
    security_opt:
      - no-new-privileges=true
    cap_drop:
      - ALL
    pids_limit: 100
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 1G
  • read_only: Das Root-Dateisystem ist schreibgeschützt – Schreibpfade werden einzeln als Volume oder tmpfs freigegeben.
  • cap_drop ALL: Der Container startet ohne Linux-Capabilities. Braucht ein Dienst eine (z. B. NET_BIND_SERVICE für Ports unter 1024), wird sie gezielt wieder ergänzt.
  • pids_limit: Begrenzt Prozesse – schützt vor Fork-Bombs im Container.
  • deploy.limits: CPU- und RAM-Limits wie in allen Artikeln der Serie.

Wichtig: Nicht jeder Dienst verträgt read_only sofort – beim Ausrollen Logs prüfen und Ausnahme-Pfade dokumentieren, statt den Schutz wieder komplett zu entfernen.

Secrets statt Klartext-Passwörter

In den Blog-Artikeln tauchen Passwörter immer wieder direkt in der Compose-Datei auf – für den Produktivbetrieb gehört das in eine geschützte .env-Datei:

# Datei: .env (im Stack-Ordner)
DB_PASSWORD=MeinGeheimesPasswort
# lange, zufällige Zeichenkette erzeugen:
openssl rand -hex 32
# docker-compose.yml
services:
  app:
    environment:
      - DB_PASSWORD=${DB_PASSWORD}
  • chmod 600 .env und die Datei nie in Git committen.
  • Werden mehrere Nutzer am Server gepflegt, ist ein Passwort-Manager die bessere Ablage als eine Datei.
  • Env-Variablen sind im laufenden Container für jeden lesbar, der docker inspect darf – für echte Geheimnisse später Docker Secrets (Ausblick Teil 6).

Updates: selektiv mit Watchtower

Automatische Updates gab es in Teil 2 für den Host – für Container übernimmt das Watchtower. Der wichtigste Punkt aus dem Blog-Artikel: selektiv arbeiten.

services:
  watchtower:
    image: containrrr/watchtower
    command: --cleanup --schedule "0 4 * * *"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  • Labels nur dort setzen, wo ein Neustart gefahrlos ist: com.centurylinklabs.watchtower.enable=true.
  • Datenbanken und Stateful-Dienste von der Automatik ausnehmen.
  • Images pinnen (z. B. image: app:2.3.1) statt blind latest – Updates werden so zu bewussten Schritten.

Stack-Backups: Volumes & Compose-Dateien

Ein Container-Backup besteht aus zwei Teilen: den Compose-Dateien (Konfiguration) und den Volumes/Bind-Mounts (Daten). Die Compose-Dateien sind schnell gesichert:

sudo tar -czf /srv/backup/stacks-2026-09-06.tar.gz -C /opt stacks

Für Volumes gibt es zwei Wege: entweder grafisch mit Duplicati (Artikel) oder direkt im Borg-Workflow aus Teil 4 – am sichersten mit gestoppten Containern. Wichtig: docker compose stop hält die Dienste nur an und lässt Container und Netzwerke intakt – docker compose down würde sie erst löschen und die Ausfallzeit unnötig verlängern:

#!/bin/sh
cd /opt/stacks/app || exit 1

# Dienste anhalten – Container & Netzwerke bleiben erhalten
docker compose stop

# Notbremse: Egal ob das Backup klappt oder nicht – die Container starten wieder.
# borg create bricht bei Fehlern ab (z. B. volle Platte), dank trap läuft
# "docker compose start" in jedem Fall beim Verlassen des Skripts.
trap 'docker compose start' EXIT

# Archivname mit dynamischem Datum – keine Kollisionen am Folgetag
borg create --stats /mnt/backup/borg-repo::stack-app-$(date +%Y-%m-%d) /opt/stacks/app
borg prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6
Merksatz: Erst der Restore-Test macht aus einem Backup ein Backup – auch für Container-Volumes.

Monitoring & Ressourcen im Blick

Uptime Kuma aus der Blog-Serie überwacht die Dienste von außen – von innen kommen diese Checks dazu:

docker compose ps
docker stats --no-stream
docker logs --tail 100 app
  • docker stats zeigt, ob die Limits aus Teil 5 realistisch sind oder ein Dienst an der RAM-Grenze arbeitet.
  • Uptime-Kuma-Monitore zusätzlich auf HTTP-Inhalte prüfen lassen, nicht nur auf „Port offen“.
  • Wöchentlich ss -tulpn (Teil 3) gegen die Liste der erwarteten Container-Ports abgleichen.

Häufige Probleme

ProblemLösung
Container startet nicht mit read_onlyLogs prüfen: fehlende Schreibpfade einzeln als Volume/tmpfs ergänzen – nicht den Schutz entfernen.
Dienst braucht Port unter 1024cap_add: [NET_BIND_SERVICE] ergänzen statt cap_drop zu entfernen.
Passwort steht noch in der Compose-DateiIn .env auslagern, Datei mit chmod 600, Stack neu erstellen.
Watchtower startet Datenbank neuLabel enable=false an stateful Container setzen und Updates manuell planen.
Backup scheint zu fehlenVolumes sind nicht in ./backups – Mount-Pfade des Stacks prüfen und Restore testen.
docker-Gruppe wurde doch benötigtBesser Rootless-Docker einrichten (Ausblick Teil 6) statt dauerhaft Root-Rechte zu verteilen.

Fazit & Serien-Ende

Mit Teil 5 ist der Kreis geschlossen: Debian 13 wird installiert (Teil 1), gehärtet (Teil 2), abgeschottet (Teil 3), überwacht und gesichert (Teil 4) – und beherbergt jetzt Dienste, die nach denselben Standards laufen. Die Grundsätze lassen sich auf jeden Stack aus der Blog-Serie übertragen.

Die 4 Merksätze aus Teil 5: ① read_only + cap_drop ALL als Standard ② Limits setzen, nie ohne RAM-/CPU-Grenze starten ③ Secrets gehören in die .env, nicht in die Compose-Datei ④ Updates und Backups automatisieren, Restore regelmäßig testen

Weiter zu Teil 6: Rootless Docker, Podman, Docker Secrets & seccomp – Container im Produktivbetrieb.

R
...

Wir betreiben unsere komplette Infrastruktur selbst auf Open-Source-Software und schreiben nur über Tools, die wir im Alltag wirklich einsetzen. Fragen zum Artikel? Schreib uns.