Docker-Compose-Secrets einrichten: Umgebungsvariablen verraten oft zu viel

|Autor: QUASA-Redaktion|5 Min. Lesezeit
Docker-Compose-Secrets einrichten: Umgebungsvariablen verraten oft zu viel

Passwörter und API-Schlüssel lassen sich in Docker Compose als Dateien gezielt den Diensten bereitstellen, die sie benötigen. Die Docker-Anleitung zu Compose-Secrets beschreibt die Freigabe pro Dienst und den Dateipfad /run/secrets/<secret_name> im Container. Der geheime Wert muss dadurch weder in der Compose-Datei noch in einer Umgebungsvariable des Dienstes stehen.

Das verringert das Risiko einer unbeabsichtigten Offenlegung: Umgebungsvariablen können bei der Fehlersuche in Logs landen oder für weitere Prozesse sichtbar sein. Die Anwendung muss das Secret allerdings aus einer Datei lesen können. Manche Images unterstützen dafür eine Variable mit der Endung _FILE, deren Wert nur den Dateipfad enthält; diese Konvention funktioniert nicht automatisch bei jeder Anwendung. Das folgende Beispiel setzt Linux-Container voraus.

Secret-Datei anlegen und einem Dienst zuweisen

Das Beispiel verwendet einen ausdrücklich fiktiven Testwert. Legen Sie in einer Linux-Shell mit mkdir -p secrets ein Verzeichnis an und schreiben Sie mit printf '%s' 'testwert-ersetzen' > secrets/api_key.txt die Datei. Für einen echten Schlüssel sollte der Wert über einen geeigneten Bereitstellungsweg in die Datei gelangen, statt als Klartext in einem gespeicherten Shell-Befehl oder Skript zu stehen.

Speichern Sie die folgenden beiden Zeilen als compose.yaml. Die kompakte Schreibweise ist gültiges YAML: app erhält das Secret api_key, ohne_secret hat keine entsprechende Zuweisung.

services: {app: {image: alpine:latest, command: ["sh", "-c", "test -s /run/secrets/api_key || exit 1; sleep 3600"], secrets: [api_key]}, ohne_secret: {image: alpine:latest, command: ["sleep", "3600"]}}

secrets: {api_key: {file: ./secrets/api_key.txt}}

Starten Sie die Dienste mit docker compose up -d. Der Befehl von app prüft, ob die eingebundene Datei Inhalt hat, und hält den Container anschließend für die Zugriffskontrolle am Laufen. Er gibt den Testwert nicht aus. In einem echten Dienst liest die Anwendung /run/secrets/api_key selbst oder erhält diesen Pfad über eine vom Image unterstützte _FILE-Variable. Ein Secret unter services bereitzustellen genügt nicht, wenn das Programm den Dateipfad gar nicht nutzt.

Zugriff und Dateirechte prüfen

Die Definition unter dem obersten secrets-Abschnitt benennt zunächst nur die Quelle. Erst die Zuweisung beim Dienst gibt dessen Container Zugriff; die Compose-Referenz für Dienst-Secrets beschreibt den Mount unter /run/secrets und die Rechteoptionen. Bei einer lokalen file-Quelle verwendet Compose einen Bind-Mount. Die Angaben uid, gid und mode in der Secret-Zuweisung werden für diese Quelle ignoriert; ein dort eingetragener Modus schützt die Host-Datei daher nicht.

Begrenzen Sie auf einem Linux-Host den lokalen Zugriff beispielsweise mit chmod 700 secrets und chmod 600 secrets/api_key.txt. Prüfen Sie dabei Eigentümer und Benutzerkennung des Container-Prozesses: Läuft die Anwendung ohne Root-Rechte, kann eine nur für den Dateieigentümer lesbare Quelle für sie unzugänglich sein. Maßgeblich ist, ob der tatsächliche Prozess die eingehängte Datei lesen darf, nicht allein, ob der Container gestartet ist.

Mit docker compose exec app sh -c 'test -r /run/secrets/api_key' prüfen Sie die Lesbarkeit im berechtigten Dienst, ohne den Inhalt auszugeben. docker compose exec ohne_secret sh -c 'test ! -e /run/secrets/api_key' kontrolliert, dass der zweite Dienst diese Datei nicht erhalten hat. Diese Prüfung zeigt die Freigabe zwischen den Beispieldiensten; sie bewertet keine anderen Zugriffswege auf den Host oder eine möglicherweise weitreichend berechtigte Anwendung.

Quelldatei aus Git, Image und Logs heraushalten

Die Secret-Quelle bleibt als Datei auf dem Host vorhanden. Tragen Sie /secrets/ in die .gitignore des Projekts ein, bevor Sie einen echten Schlüssel anlegen oder Änderungen committen. Verwendet ein Docker-Build das Projektverzeichnis als Build-Kontext, gehört derselbe Ausschluss in die .dockerignore am Stamm dieses Kontexts. Andernfalls kann die Datei für Build-Schritte erreichbar sein und durch eine unbedachte COPY-Anweisung ins Image gelangen.

Eine .gitignore entfernt bereits versionierte Dateien nicht aus der Git-Historie. Wurde ein echter Schlüssel eingecheckt, behandeln Sie ihn als offengelegt und ersetzen ihn beim ausstellenden Dienst. Auch ein korrekt eingebundenes Secret kann die Anwendung selbst preisgeben, etwa in einer ausführlichen Fehlermeldung oder einem Konfigurationsdump. Lassen Sie Diagnosen deshalb Dateiexistenz, Lesbarkeit und Startstatus zeigen, nicht den gelesenen Wert. Die dienstweise Freigabe kontrolliert den Mount, nicht die spätere Ausgabe durch das Programm.

Einen Schlüssel austauschen

Für eine nachvollziehbare Rotation legen Sie eine neue, geschützt gespeicherte Datei an und ändern den file-Pfad des bestehenden Secrets in compose.yaml auf diese Datei. Erstellen Sie den betroffenen Container anschließend mit docker compose up -d --force-recreate app neu. Damit wird der Mount für die neue Dateiquelle eingerichtet; zugleich startet eine Anwendung neu, die Zugangsdaten nur beim Start einliest. Verlassen Sie sich bei einem bestehenden Bind-Mount nicht darauf, dass das bloße Ersetzen der Quelldatei jeden laufenden Prozess zuverlässig auf den neuen Wert umstellt.

Prüfen Sie danach mit einer passenden Anwendungshandlung, ob die Verbindung mit dem neuen Schlüssel funktioniert. Widerrufen Sie den alten Schlüssel erst, wenn der neue im benötigten Dienst wirksam ist. Das Ändern einer lokalen Datei widerruft bereits ausgegebene Zugangsdaten beim Anbieter nicht. Ob beide Schlüssel vorübergehend parallel gültig sein können, hängt vom ausstellenden Dienst ab; diese Eigenschaft steuert Compose nicht.

Die Grenze zu Swarm und externen Secret-Stores

Lokale Compose-Secrets aus file-Quellen sind eingehängte Dateien und kein zentral verwalteter, verschlüsselter Tresor. Die Docker-Dokumentation zu Swarm-Secrets beschreibt für Swarm verschlüsselte Übertragung und Speicherung im Cluster. Diese Eigenschaften gelten nicht allein deshalb für die lokale Quelldatei, weil beide Varianten in einer Compose-Datei mit secrets bezeichnet werden.

Wer Secrets über mehrere Hosts verteilen, Zugriffe zentral verwalten oder die Rotation automatisieren muss, benötigt dafür eine passende Orchestrierungsplattform oder einen externen Secret-Store. Bei einem einzelnen Compose-Host entscheidet dagegen vor allem die Kontrolle über die Quelldatei, die Berechtigung des Container-Prozesses und das Verhalten der Anwendung beim Einlesen und Protokollieren über das verbleibende Risiko.

Lesen Sie auch:

Teilen:

Newsletter abonnieren

Erhalten Sie die neuesten Nachrichten zu Web3, KI und Krypto direkt in Ihren Posteingang.

0