statt Passwoerter in Environment Variablen
Zugangsdaten in der environment Sektion einer compose.yaml landen in docker inspect, in Prozesslisten und oft versehentlich in Log-Ausgaben. Der secrets Block in Docker Compose loest dieses Problem, indem Zugangsdaten als Dateien im Container bereitgestellt werden, statt als sichtbare Umgebungsvariablen, und schafft damit einen deutlich saubereren Umgang mit Passwoertern und API-Schluesseln.
Inhaltsverzeichnis
- 1. Warum Environment Variablen fuer Zugangsdaten problematisch sind
- 2. Der secrets Block in Docker Compose: Grundlagen
- 3. File basierte Secrets: lokale Entwicklung absichern
- 4. Externe Secrets: bereits vorhandene Docker Secrets nutzen
- 5. Der _FILE Suffix: Anwendungen ohne Aenderung secret-faehig machen
- 6. Praxisbeispiel: MySQL Root-Passwort als Secret
- 7. Praxisbeispiel: PHP und Magento mit Secrets fuer API-Keys
- 8. Secrets aus der Versionierung fernhalten
- 9. Secrets im Vergleich zu Environment Variablen und .env Dateien
- 10. Zusammenfassung
- 11. FAQ
1. Warum Environment Variablen fuer Zugangsdaten problematisch sind
In vielen compose.yaml Dateien landen Datenbank-Passwoerter, API-Schluessel und andere Zugangsdaten direkt in der environment Sektion. Das funktioniert technisch, ist aber aus Sicherheitssicht problematisch, weil Umgebungsvariablen an mehreren Stellen sichtbar sind, die man selten bedenkt. Mit docker inspect kann jeder mit Zugriff auf den Docker-Daemon die kompletten Umgebungsvariablen eines laufenden Containers auslesen, inklusive aller Passwoerter im Klartext.
Zusaetzlich landen Umgebungsvariablen haeufig in Prozesslisten, etwa wenn eine Anwendung sie beim Start protokolliert, oder in Crash-Dumps, die zur Fehleranalyse an Dritte weitergegeben werden. Auch viele Logging-Frameworks geben beim Start aus Versehen die komplette Umgebung aus, wenn ein Debug-Modus aktiv ist. Docker Compose Secrets loesen dieses Problem strukturell, indem Zugangsdaten nicht als Umgebungsvariable, sondern als Datei im Dateisystem des Containers bereitgestellt werden, typischerweise unter /run/secrets/.
Der entscheidende Unterschied: Eine Datei unter /run/secrets/ wird nicht automatisch von docker inspect angezeigt und landet nicht in der Prozessumgebung, die viele Monitoring- und Log-Tools standardmaessig mitschneiden. Wer Docker Compose Secrets konsequent fuer alle Zugangsdaten nutzt, reduziert die Angriffsflaeche erheblich, ohne dass die Anwendung selbst grundlegend umgebaut werden muss.
2. Der secrets Block in Docker Compose: Grundlagen
Docker Compose kennt zwei Ebenen fuer Secrets: die Top-Level secrets Definition, die festlegt, woher ein Secret kommt, und die service-lokale secrets Liste, die festlegt, welche Secrets ein bestimmter Service tatsaechlich erhaelt. Diese Trennung erlaubt es, ein Secret einmal zu definieren und gezielt nur den Services zur Verfuegung zu stellen, die es tatsaechlich brauchen, statt es pauschal in jeden Container zu injizieren.
Jedes Secret wird beim Start des Containers als Datei unter /run/secrets/<secret-name> gemountet, mit dem Dateiinhalt als eigentlichem Secret-Wert. Diese Datei ist read-only und nur fuer den Root-Benutzer im Container standardmaessig lesbar, was zusaetzliche Isolation gegenueber anderen Prozessen im selben Container-Netzwerk bietet, verglichen mit einer fuer alle Prozesse sichtbaren Umgebungsvariable.
# compose.yaml — basic secrets block
services:
api:
image: myapp/api:latest
secrets:
- db_password
- api_key
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
file: ./secrets/api_key.txt
Im Container ist der Inhalt von db_password.txt anschliessend unter /run/secrets/db_password verfuegbar. Die Anwendung liest die Datei beim Start ein, statt eine Umgebungsvariable abzufragen. Dieses Muster funktioniert mit praktisch jeder Programmiersprache, weil Dateizugriff eine Grundfunktion ist, die keine zusaetzliche Bibliothek erfordert.
3. File basierte Secrets: lokale Entwicklung absichern
Die einfachste Form von Docker Compose Secrets ist die file basierte Variante, bei der eine lokale Datei als Quelle dient. Fuer die lokale Entwicklung bedeutet das: Zugangsdaten liegen als einzelne Textdateien in einem secrets Verzeichnis, das explizit aus der Versionierung ausgeschlossen wird, waehrend eine secrets.example Vorlage mit Platzhaltern eingecheckt wird, damit neue Teammitglieder wissen, welche Secrets benoetigt werden.
Ein haeufiger Anwendungsfall ist die Trennung zwischen Entwicklungs- und Produktionswerten. In der lokalen compose.yaml zeigen die file Eintraege auf harmlose Entwicklungswerte, waehrend in produktionsnahen Umgebungen dieselbe Struktur mit echten, ueber ein Secret-Management-System verwalteten Werten befuellt wird. Die Anwendung selbst muss dabei nicht wissen, ob sie mit Entwicklungs- oder Produktionswerten arbeitet, weil sie immer denselben Dateipfad unter /run/secrets/ liest.
# Set up local secrets directory (excluded from version control)
mkdir -p secrets
echo -n "dev-only-password" > secrets/db_password.txt
echo -n "dev-api-key-12345" > secrets/api_key.txt
# Restrict permissions so only the owner can read the files
chmod 600 secrets/*.txt
# Verify the secret is visible inside the running container
docker compose exec api cat /run/secrets/db_password
4. Externe Secrets: bereits vorhandene Docker Secrets nutzen
Neben file basierten Secrets unterstuetzt Docker Compose auch externe Secrets, die bereits ausserhalb der compose.yaml existieren, etwa als Docker Swarm Secret oder ueber ein extern verwaltetes Secret-Management-System. Mit external: true verweist Compose auf ein Secret, das bereits im Docker-Daemon registriert ist, statt es aus einer lokalen Datei neu zu erzeugen. Das ist besonders relevant, wenn Secrets zentral verwaltet und von mehreren Compose-Projekten gemeinsam genutzt werden sollen.
In einer lokalen Docker Desktop oder Docker Engine Installation ohne Swarm-Modus lassen sich externe Secrets ueber docker secret create anlegen, sofern der Swarm-Modus aktiviert ist. Fuer reine Docker Compose Setups ohne Swarm ist die file basierte Variante meistens praktischer, weil sie keine zusaetzliche Swarm-Initialisierung voraussetzt und direkt mit einem einfachen docker compose up funktioniert.
# compose.yaml — external secret managed outside this project
services:
api:
image: myapp/api:latest
secrets:
- source: db_password
target: db_password
mode: 0400
secrets:
db_password:
external: true
name: production_db_password
5. Der _FILE Suffix: Anwendungen ohne Aenderung secret-faehig machen
Nicht jede Anwendung liest Konfigurationswerte aus einer Datei ein. Viele Frameworks und Bibliotheken erwarten weiterhin eine klassische Umgebungsvariable. Ein etabliertes Muster, das viele offizielle Docker Images unterstuetzen, etwa die offiziellen MySQL und Postgres Images, ist der _FILE Suffix. Statt DB_PASSWORD direkt zu setzen, wird DB_PASSWORD_FILE mit dem Pfad zur Secret-Datei gesetzt, und der Entrypoint des Images liest die Datei selbststaendig ein und setzt die eigentliche Variable intern.
Dieses Muster verbindet die Sicherheit von Secrets mit der Einfachheit von Umgebungsvariablen, ohne dass die Anwendung selbst angepasst werden muss, solange sie ein Image verwendet, das den _FILE Suffix unterstuetzt. Fuer eigene Anwendungen, die diesen Mechanismus nicht mitbringen, laesst er sich leicht im Entrypoint-Skript nachbauen, indem geprueft wird, ob eine _FILE Variable gesetzt ist, und falls ja, deren Inhalt in die eigentliche Variable geladen wird.
# compose.yaml — using the _FILE suffix pattern with official images
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
MYSQL_DATABASE: magento
secrets:
- mysql_root_password
secrets:
mysql_root_password:
file: ./secrets/mysql_root_password.txt
6. Praxisbeispiel: MySQL Root-Passwort als Secret
Das offizielle MySQL Image unterstuetzt den _FILE Suffix nativ fuer MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD und mehrere weitere Variablen. Damit laesst sich ein produktionsnahes lokales Setup aufbauen, in dem das Root-Passwort niemals als Klartext-Umgebungsvariable im Container erscheint, sondern ausschliesslich als Dateiinhalt unter /run/secrets/. Der MySQL Entrypoint liest die Datei beim ersten Start ein und initialisiert die Datenbank entsprechend.
Fuer Magento-Projekte, die haeufig mehrere Datenbank-Benutzer fuer unterschiedliche Zwecke benoetigen, etwa einen Anwendungs-Benutzer mit eingeschraenkten Rechten neben dem Root-Benutzer, laesst sich dasselbe Muster fuer jeden zusaetzlichen Benutzer wiederholen. Jedes Passwort bekommt eine eigene Secret-Datei, und die Anwendung selbst liest ihre Zugangsdaten ueber denselben _FILE Mechanismus oder direkt aus /run/secrets/, je nachdem, was das verwendete Datenbank-Framework unterstuetzt.
7. Praxisbeispiel: PHP und Magento mit Secrets fuer API-Keys
Fuer PHP-Anwendungen, die keinen nativen _FILE Support mitbringen, ist das Auslesen eines Secrets eine einfache Dateioperation. Statt getenv("PAYMENT_API_KEY") aufzurufen, liest die Anwendung file_get_contents("/run/secrets/payment_api_key") und verwendet den getrimmten Inhalt als Wert. In Magento laesst sich dieses Muster in der env.php oder in einem eigenen Konfigurationsprovider kapseln, sodass der Rest der Anwendung weiterhin ganz normal auf einen Konfigurationswert zugreift, ohne von der Secrets-Implementierung im Detail zu wissen.
Ein praktischer Vorteil dieses Ansatzes: Secrets lassen sich waehrend der Laufzeit rotieren, indem die zugrunde liegende Datei ausgetauscht wird, ohne dass der Container neu gestartet werden muss, sofern die Anwendung die Datei bei jedem Zugriff neu liest statt sie einmalig zu cachen. Fuer Zugangsdaten, die sich selten aendern, ist das Caching beim ersten Lesen meist ausreichend, fuer haeufiger rotierte Werte lohnt sich ein periodisches Neueinlesen.
# Read a secret from within a running PHP container for debugging
docker compose exec php-fpm cat /run/secrets/payment_api_key
# Verify file permissions on the mounted secret
docker compose exec php-fpm stat /run/secrets/payment_api_key
# Rotate a secret without restarting: replace the source file, then
# re-run compose up to remount it into a freshly created container
docker compose up -d --force-recreate php-fpm
8. Secrets aus der Versionierung fernhalten
Ein Secret, das versehentlich in ein Git-Repository eingecheckt wird, ist faktisch kompromittiert, selbst wenn der Commit spaeter rueckgaengig gemacht wird, weil die Git-Historie den Wert weiterhin enthaelt. Fuer file basierte Docker Compose Secrets bedeutet das: Das secrets Verzeichnis mit den tatsaechlichen Werten gehoert konsequent in die .gitignore, waehrend eine secrets Vorlage mit Platzhaltern oder Beispielwerten eingecheckt wird, damit das Projekt-Setup fuer neue Teammitglieder dokumentiert bleibt.
Zusaetzlich empfiehlt sich ein Pre-Commit-Hook oder ein CI-Schritt, der ueberprueft, ob versehentlich reale Secret-Dateien mit eingecheckt wurden. Tools wie gitleaks oder trufflehog scannen ein Repository nach typischen Mustern fuer Passwoerter, API-Schluessel und Zertifikate und schlagen Alarm, bevor ein Secret tatsaechlich in die Historie gelangt. Diese Kombination aus .gitignore und automatisiertem Scanning ist die praktische Ergaenzung zum technischen Schutz durch Docker Compose Secrets.
9. Secrets im Vergleich zu Environment Variablen und .env Dateien
Fuer Zugangsdaten gibt es in Docker Compose mehrere Wege, die auf den ersten Blick aehnlich wirken, sich aber deutlich in Sicherheit und Sichtbarkeit unterscheiden. Die Wahl zwischen ihnen sollte bewusst getroffen werden, statt aus Gewohnheit immer dieselbe Variante zu nutzen.
| Methode | Sichtbar in docker inspect | In Prozessumgebung | Empfehlung fuer Zugangsdaten |
|---|---|---|---|
| environment direkt | Ja, im Klartext | Ja | Nicht geeignet fuer Passwoerter |
| .env Datei | Ja, wird zu environment | Ja | Nur fuer unkritische Konfiguration |
| Docker Compose Secrets | Nein | Nein | Empfohlen fuer Passwoerter und API-Keys |
| Externes Secret-Management | Nein | Nein | Empfohlen fuer produktive Multi-Team-Umgebungen |
Der Unterschied zwischen file basierten Secrets und einem vollwertigen externen Secret-Management-System liegt vor allem im Rotationskomfort und der zentralen Zugriffskontrolle. Fuer lokale Entwicklung und kleinere Deployments reicht der file basierte secrets Block vollstaendig aus, waehrend groessere Organisationen mit vielen Teams von einem zentralen System profitieren, das Docker Compose Secrets als externe Quelle referenzieren kann.
Mironsoft
Sichere Docker-Infrastruktur und Secrets Management
Passwoerter, die nicht mehr in docker inspect auftauchen?
Wir migrieren bestehende Docker Compose Stacks von Klartext-Environment-Variablen auf einen sauberen secrets Workflow, inklusive .gitignore-Absicherung und Rotationskonzept.
Secrets-Audit
Bestehende compose.yaml auf Klartext-Zugangsdaten in environment pruefen
Migration
Umstellung auf file basierte oder externe Secrets ohne Anwendungsausfall
Magento-Secrets
Datenbank-Zugangsdaten und Payment-API-Keys sicher in env.php einbinden
10. Zusammenfassung
Docker Compose Secrets loesen ein strukturelles Sicherheitsproblem klassischer environment Variablen: Zugangsdaten, die in docker inspect, Prozesslisten und oft auch in Logs sichtbar werden. Mit dem secrets Block werden Passwoerter und API-Schluessel stattdessen als Dateien unter /run/secrets/ bereitgestellt, entweder file basiert fuer lokale Entwicklung oder als external referenzierte Secrets aus einem zentralen Management-System. Der _FILE Suffix erlaubt es, viele offizielle Images ohne Codeaenderung secret-faehig zu nutzen.
Fuer PHP- und Magento-Projekte laesst sich derselbe Mechanismus mit einer einfachen Dateileseoperation nachbauen, wenn die Anwendung selbst keinen nativen Secrets-Support mitbringt. Kombiniert mit einer konsequenten .gitignore-Strategie und automatisiertem Secret-Scanning entsteht ein Setup, in dem Zugangsdaten weder in der Versionierung noch in leicht auslesbaren Umgebungsvariablen landen.
Docker Compose Secrets — Das Wichtigste auf einen Blick
file basiert
Lokale Datei als Secret-Quelle, ideal fuer Entwicklungsumgebungen, ausgeschlossen aus der Versionierung.
external
Referenziert ein bereits im Docker-Daemon vorhandenes Secret, geeignet fuer zentral verwaltete Zugangsdaten.
_FILE Suffix
Viele offizielle Images lesen eine Secret-Datei automatisch ein, wenn die Variable mit _FILE endet.
Nicht in docker inspect
Secrets erscheinen nicht in der sichtbaren Container-Umgebung, im Gegensatz zu environment Variablen.