Zum Hauptinhalt springen
S-EDV news
← Alle News
Docker 08.09.2026 · 5 min Lesezeit

Docker Compose Secrets statt Klartext-Umgebungsvariablen: Zugangsdaten in Self-Hosting-Projekten mit Dateirechten, .gitignore und kontrollierter Rotation richtig schützen

Viele Self-Hosting-Setups übergeben Datenbank-Passwörter und API-Schlüssel als Umgebungsvariablen. Diese Anleitung zeigt Schritt für Schritt, wie Docker Compose Secrets, das *_FILE-Pattern, restriktive Dateirechte, sichere Prüfungen und eine kontrollierte Rotation zusammenspielen.

Grafik zeigt Docker Compose Secrets Konfiguration mit Dateibaum, Schlüssel- und Schild-Symbol als sichere Alternative zu Klartext-Kennwörtern in Umgebungsvariablen KI-generiert

Typische Probleme: Passwörter stehen unter environment, .env landet in Git, docker inspect zeigt Werte, Prozesse lesen ihre Umgebung und die Rotation bleibt ungeplant.

Diese Fehlerbilder sind in kleinen Self-Hosting-Umgebungen häufig. Docker Compose Secrets lösen nicht jedes Geheimnisproblem, trennen sensible Werte aber sauber von der Konfiguration und stellen sie nur ausgewählten Diensten als Dateien bereit. Für 2026 ist das die sinnvolle Best Practice für einen einzelnen Docker-Host ohne Swarm oder externen Secret Manager.

Warum .env-Dateien kein Secret-Speicher sind

Eine .env-Datei eignet sich für unkritische Werte wie Portnummern oder Image-Tags, nicht für Passwörter. Compose übergibt Werte häufig als Prozessumgebung an den Container, sichtbar über Inspektionsdaten, Prozessinformationen oder Fehlerberichte. Ein Eintrag in .gitignore reduziert Git-Leaks, verschlüsselt die Datei aber nicht und entfernt bereits veröffentlichte Git-Historie nicht.

  • Keine Passwörter direkt unter environment eintragen.
  • Keine Geheimnisse in .env ablegen.
  • Keine echten Zugangsdaten in Beispielen dokumentieren.
  • Bereits veröffentlichte Werte sofort widerrufen und ersetzen.

Was Docker Compose Secrets tatsächlich leisten

Ein Secret wird auf der obersten Compose-Ebene unter secrets definiert. Erst die zusätzliche Freigabe unter services macht es für einen Container verfügbar. Lokales Compose bindet die Quelldatei standardmäßig als Datei unter /run/secrets/<name> ein. Der Wert erscheint dadurch nicht als normale Umgebungsvariable.

Wichtige Grenze: Lokales Compose bind-mountet Secrets vom Host. Anders als Docker Swarm bietet es keinen verschlüsselten Control-Plane-Schutz. Die Hostdatei bleibt der Schutzanker.

MethodeSpeicherortGrenze
environmentProzessumgebungÜber Inspektion/Diagnose sichtbar
.envMeist in ProzessumgebungKein Secret-Speicher, Risiko durch Git
Compose Secret/run/secrets/nameQuelldatei bleibt auf Host
Swarm SecretDatei im autorisierten TaskBenötigt Swarm-Modus

Schritt 1: Verzeichnis und Secret-Datei sicher anlegen

Legen Sie Secrets außerhalb öffentlich erreichbarer Verzeichnisse an. Das Passwort wird verdeckt eingelesen, nicht als Klartext in den Befehl geschrieben, damit es nicht in der Shell-Historie landet.

cd /srv/mein-stack
install -m 700 -d secrets
umask 077
read -rsp "Neues Passwort: " DB_PASSWORD
printf '\n'
printf '%s' "$DB_PASSWORD" > secrets/db_password.txt
unset DB_PASSWORD
chmod 600 secrets/db_password.txt
stat -c '%a %U:%G %n' secrets/db_password.txt

Die letzte Zeile muss für die Quelldatei den Modus 600 zeigen, nur der Besitzer darf lesen und schreiben. Angaben wie uid, gid und mode in der langen Secret-Syntax wirken bei einer lokalen Datei anders als bei Swarm, weil Compose einen Bind-Mount verwendet. Entscheidend sind die Rechte der Quelldatei auf dem Host und ein passender Benutzer im Container.

Schritt 2: Git-Leaks mit .gitignore verhindern

Ignorieren Sie das gesamte Secret-Verzeichnis, eine leere Platzhalterdatei bleibt sichtbar. Eine bereits getrackte Datei wird durch .gitignore nicht automatisch aus Git entfernt.

# /srv/mein-stack/.gitignore
secrets/*
!secrets/.gitkeep
touch secrets/.gitkeep
git check-ignore -v secrets/db_password.txt

Zeigt git check-ignore keine Regel, nicht committen. War das Passwort bereits Teil eines Commits, reicht Löschen nicht: Wert sofort rotieren, Historie nur abgestimmt bereinigen.

Schritt 3: Secret auf oberster Ebene und am Dienst definieren

Dieses Beispiel startet PostgreSQL mit dateibasiertem Initialpasswort. Unten registriert die Definition die Hostdatei als Compose Secret, der Eintrag im Dienst gewährt ausschließlich db Zugriff. POSTGRES_PASSWORD_FILE ist das vom offiziellen PostgreSQL-Image unterstützte *_FILE-Pattern.

services:
  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]

volumes:
  postgres_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

Ohne secrets: - db_password im Dienst wird die Datei dort nicht bereitgestellt. Kein weiterer Dienst sollte das Secret erhalten, wenn er es nicht benötigt (geringste Berechtigung).

Schritt 4: Das *_FILE-Pattern für weitere Apps nutzen

Compose liest die Datei nicht automatisch für die Anwendung ein. Software oder Entrypoint müssen eine *_FILE-Variable unterstützen, der Name ist anwendungsspezifisch. Immer die Image-Dokumentation prüfen. Typisches Schema:

services:
  app:
    image: registry.example.org/meine-app:tag
    environment:
      APP_DB_HOST: db
      APP_DB_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

Der Image-Name ist ein Platzhalter, durch ein geprüftes Image ersetzen. Unterstützt eine App nur APP_DB_PASSWORD, erzeugt bloßes Anhängen von _FILE keine Funktion, dann braucht es einen dokumentierten Entrypoint oder externen Secret Manager. Das Secret nicht per Shell-Konstruktion zurück in eine Umgebungsvariable kopieren, sonst geht der Vorteil verloren.

Schritt 5: Konfiguration prüfen, ohne Geheimnisse auszugeben

Prüfen Sie zuerst die Syntax ohne gerenderte Konfiguration auf dem Bildschirm. docker compose config --quiet validiert das Modell und gibt bei Erfolg nichts aus. --quiet ist für Protokolle und Support-Sitzungen die vorsichtigste Variante, weil keine interpolierten Werte ausgegeben werden.

docker compose config --quiet
docker compose up -d
docker compose ps

Nur Existenz und Lesbarkeit der Datei im Container prüfen, nicht ihren Inhalt:

docker compose exec db sh -c 'test -r /run/secrets/db_password && echo "Secret-Datei ist lesbar"'
  • Kein cat /run/secrets/db_password in gemeinsam sichtbaren Terminals ausführen.
  • Keine Secret-Werte in Tickets oder Chats kopieren.
  • Keine vollständige Prozessumgebung an Support-Bundles anhängen.

Schritt 6: Secrets kontrolliert rotieren

Eine geänderte Quelldatei ändert nicht automatisch das Kennwort im Zielsystem. Zuerst die Zugangsdaten dort ändern, danach die Secret-Datei atomar ersetzen und den Dienst kontrolliert neu erstellen. Wartungsfenster einplanen.

  1. Aktuelles Backup erstellen und Wiederherstellung prüfen.
  2. Neues starkes Passwort verdeckt erzeugen oder aus Passwortmanager übernehmen.
  3. Passwort im Zielsystem sicher ändern.
  4. Neue Secret-Datei mit Modus 600 atomar verschieben.
  5. Nur betroffene Dienste neu erstellen.
  6. Healthcheck, Anmeldung und Logs prüfen.
  7. Altes Passwort erst nach Prüfung endgültig verwerfen.
cd /srv/mein-stack
umask 077
read -rsp "Rotiertes Passwort: " NEW_PASSWORD
printf '\n'
printf '%s' "$NEW_PASSWORD" > secrets/db_password.txt.new
unset NEW_PASSWORD
chmod 600 secrets/db_password.txt.new
mv secrets/db_password.txt.new secrets/db_password.txt
docker compose up -d --force-recreate db
docker compose logs --since 5m db

Die Kennwortänderung in PostgreSQL ist bewusst nicht als SQL-Befehl dargestellt, sie hängt vom Rollenmodell ab. Bei mehreren Diensten die Reihenfolge planen, ein unkoordinierter Wechsel verursacht sonst Verbindungsfehler.

Backups ohne neue Klartextkopien planen

Datenbackup und Secret-Backup haben unterschiedliche Zwecke. Ohne Zugangsdaten scheitert eine Wiederherstellung, eine unverschlüsselte Kopie des Projektordners vergrößert aber das Risiko. Secrets nur bei Bedarf sichern, getrennt und verschlüsselt.

  • Secret-Verzeichnis aus unverschlüsselten Datei-Backups ausschließen.
  • Benötigte Secrets in Passwortmanager oder verschlüsseltem Tresor sichern.
  • Backup-Zugriffe protokollieren, auf wenige Konten begrenzen.
  • Wiederherstellung regelmäßig in isolierter Umgebung testen.
  • Nach möglichem Backup-Abfluss alle enthaltenen Secrets rotieren.

Vertiefend helfen Docker Compose absichern, Docker sicher aktualisieren und das Homepage-Dashboard-Beispiel.

Fazit: Bessere Trennung, aber kein Tresor

Compose Secrets halten sensible Werte aus Compose-Datei und Prozessumgebung heraus. Dateirechte, .gitignore und das *_FILE-Pattern bleiben Pflicht.

Quellen

Docker ComposeDocker SecretsSelf-HostingContainersicherheitPasswörterDevOps