Docker auf Debian 13 richtig betreiben – 15 Dinge, die Administratoren wissen sollten

Docker auf einem Debian-Server zu installieren ist einfach. Docker dauerhaft, sicher und wartbar zu betreiben, ist eine andere Geschichte. Spätestens wenn mehrere Anwendungen wie Reverse Proxies, Datenbanken, Passwortmanager, Monitoring oder eigene Webanwendungen auf einem Host laufen, reichen zufällig zusammenkopierte Compose-Dateien nicht mehr aus.

Dieser Guide zeigt 15 Punkte für den professionelleren Docker-Betrieb auf Debian 13 – inklusive konkreter Shell-Beispiele für Installation, Compose, Rechte, Netzwerke, Firewall, Logging, Updates und Backups.

1. Docker aus einer konsistenten Quelle installieren

Mische nicht unkontrolliert docker.io, docker-ce, manuelle Compose-Binaries und alte Paketreste. Prüfe zunächst den Bestand:

docker --version
docker compose version
docker info
dpkg -l | grep -E 'docker|containerd'

Eine konsistente Installation umfasst typischerweise Docker Engine, CLI, containerd, Buildx und das Compose-Plugin.

2. docker compose statt Legacy-docker-compose

Die moderne Syntax verwendet Compose als Docker-CLI-Plugin:

docker compose up -d
docker compose down
docker compose pull
docker compose logs -f
docker compose ps

Gerade nach Migrationen von älteren Debian-Systemen lohnt sich die Prüfung:

docker compose version
docker-compose --version

3. Saubere Verzeichnisstruktur für Container-Projekte

Verstreue Compose-Dateien nicht beliebig über den Server. Eine nachvollziehbare Struktur könnte so aussehen:

/opt/docker/
├── nginx-proxy-manager/
│   ├── compose.yml
│   └── data/
├── application/
│   ├── compose.yml
│   ├── .env
│   ├── config/
│   └── data/
└── monitoring/
    └── compose.yml

Wichtig ist Konsistenz: Ein Projekt sollte Konfiguration, Compose-Datei und zugehörige persistente Daten klar erkennbar zusammenhalten.

4. Wichtige Daten niemals nur im Container speichern

Container sind austauschbar. Persistente Daten gehören in Volumes oder Bind-Mounts.

services:
  database:
    image: mariadb:11
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Volumes prüfen:

docker volume ls
docker volume inspect db_data

Für Konfigurationsdateien ist ein read-only Bind-Mount häufig sinnvoll:

volumes:
  - ./config/app.conf:/etc/app/app.conf:ro

5. Restart-Policies setzen

Ein Server startet neu, Docker wird aktualisiert oder ein Prozess beendet sich unerwartet. Für viele Dienste ist daher sinnvoll:

restart: unless-stopped

Die Einstellung prüfen:

docker inspect CONTAINERNAME \
  --format '{{.HostConfig.RestartPolicy.Name}}'

Auch der Docker-Dienst selbst sollte beim Systemstart verfügbar sein:

sudo systemctl enable docker.service
sudo systemctl enable containerd.service
systemctl status docker

6. Die Docker-Gruppe bedeutet weitreichende Rechte

Der bequeme Befehl:

sudo usermod -aG docker $USER
newgrp docker

erspart zwar sudo, ist aber kein harmloser Komfortzugriff. Mitglieder der Docker-Gruppe erhalten weitreichende Möglichkeiten über den Docker-Daemon.

getent group docker

Prüfe daher bewusst, wer Mitglied dieser Gruppe ist.

7. Rootless Docker bewusst bewerten

Docker kann auch im Rootless-Modus betrieben werden. Das kann die Rechte-Trennung verbessern, bringt aber Unterschiede bei Netzwerk, Storage und bestimmten Container-Anforderungen mit sich. Rootless Docker sollte deshalb bewusst in die vorhandene Serverarchitektur passen und nicht automatisch als universelle Lösung betrachtet werden.

8. Das Docker-Socket niemals ungeschützt veröffentlichen

Der lokale Socket befindet sich üblicherweise hier:

ls -l /var/run/docker.sock

Ein ungeschützter TCP-Zugriff auf den Docker-Daemon wäre ein erhebliches Sicherheitsrisiko. Für Remote-Administration sind abgesicherte Verfahren wie SSH sinnvoll.

docker context create \
  --docker host=ssh://user@server \
  mein-server

docker context use mein-server

9. Docker und Firewall-Regeln verstehen

Bei Docker darf man nicht einfach davon ausgehen, dass eine UFW-Regel automatisch jeden veröffentlichten Container-Port wie erwartet schützt. Prüfe deshalb regelmäßig:

docker ps

Ein Mapping wie:

0.0.0.0:8080->80/tcp

bedeutet, dass der Dienst auf allen Interfaces veröffentlicht wird. Soll ein Dienst nur lokal erreichbar sein:

ports:
  - "127.0.0.1:8080:80"

10. Docker-Netzwerke segmentieren

Eine Datenbank muss normalerweise nicht direkt vom Internet erreichbar sein. Trenne Frontend und Backend:

networks:
  frontend:
  backend:
services:
  proxy:
    networks:
      - frontend

  app:
    networks:
      - frontend
      - backend

  database:
    networks:
      - backend

Innerhalb des Compose-Netzwerks kann die Anwendung den Service-Namen direkt verwenden, beispielsweise:

database:3306

11. latest ist keine Update-Strategie

Statt:

image: mariadb:latest

ist eine kontrollierbare Version oft besser:

image: mariadb:11

Updates bewusst durchführen:

docker compose pull
docker compose up -d
docker compose ps

12. Docker-Logs rotieren, bevor die Platte voll ist

Prüfe den Speicherverbrauch:

df -h
docker system df

Eine mögliche Konfiguration in /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

Anschließend:

sudo systemctl restart docker

13. daemon.json vor dem Neustart validieren

Eine fehlerhafte Daemon-Konfiguration kann Docker am Start hindern.

sudo dockerd --validate \
  --config-file=/etc/docker/daemon.json

Danach:

sudo systemctl restart docker
systemctl status docker
journalctl -u docker -n 100 --no-pager

14. Backups: Compose-Dateien allein reichen nicht

Sichere sowohl Konfigurationen als auch persistente Daten und Datenbanken. Volumes auflisten:

docker volume ls

Beispiel für ein Volume-Backup:

docker run --rm \
  -v mein_volume:/source:ro \
  -v "$PWD":/backup \
  alpine \
  tar czf /backup/mein_volume.tar.gz -C /source .

Für MariaDB ist ein konsistenter Dump häufig die bessere Wahl:

docker compose exec -T database \
  mysqldump -u root -p MEINE_DATENBANK \
  > backup.sql

Passwörter sollten dabei nicht unnötig direkt in der Shell-History landen.

15. Nicht nur Container, sondern den gesamten Server warten

Ein Docker-Host besteht aus mehr als Containern. Regelmäßig prüfen:

sudo apt update
sudo apt upgrade

docker version
docker compose version

uname -a
df -h
free -h

docker system df
docker ps -a
docker images

Ungenutzte Ressourcen können geprüft und bei Bedarf bereinigt werden:

docker system prune

Mit aggressiveren Varianten wie docker system prune -a --volumes sollte man auf produktiven Systemen ausgesprochen vorsichtig sein.

Bonus: Solide Compose-Grundlage

services:
  app:
    image: example/application:1.2
    restart: unless-stopped
    environment:
      TZ: Europe/Berlin
    volumes:
      - ./data:/app/data
    networks:
      - frontend
      - backend

  database:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: example
      MARIADB_USER: example
      MARIADB_PASSWORD: CHANGE_ME
      MARIADB_ROOT_PASSWORD: CHANGE_ME_TOO
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend

volumes:
  db_data:

networks:
  frontend:
  backend:

Mein Docker-Admin-Check für Debian 13

docker version
docker compose version

docker ps -a
docker images
docker network ls
docker volume ls

docker system df

df -h
free -h

systemctl status docker
journalctl -u docker -n 50 --no-pager

docker ps --format "table {{.Names}}	{{.Image}}	{{.Ports}}	{{.Status}}"

Fazit

Docker auf Debian 13 ist hervorragend für den Betrieb mehrerer Anwendungen geeignet – sofern Datenpersistenz, Rechte, Netzwerke, Firewall, Logging, Backups und Updates bewusst geplant werden. Gerade beim Wechsel von Debian 12 auf Debian 13 ist der richtige Zeitpunkt gekommen, alte Compose-Installationen aufzuräumen und aus einem „es läuft irgendwie“-Server eine wartbare Container-Infrastruktur zu machen.

About Sille-Solutions