Docker Compose Secrets statt Environment Variablen nutzen
AI generated
FROM
RUN
Docker · Docker Compose · Secrets · Sicherheit
Docker Compose Secrets
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.

17 Min. Lesezeit secrets · file · external · _FILE Suffix Docker Compose 2.x

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.

11. FAQ: Docker Compose Secrets statt Environment Variablen

1Warum sind Secrets sicherer als Environment Variablen?
Secrets erscheinen nicht in docker inspect, environment Variablen dagegen im Klartext.
2Wie definiere ich ein file basiertes Secret?
Ueber den Top-Level secrets Schluessel mit file: Pfad, dann in der service-lokalen secrets Liste zuweisen.
3file vs. external Secrets?
file liest lokal, external referenziert ein bereits im Daemon existierendes Secret.
4Was macht der _FILE Suffix?
Der Entrypoint liest die referenzierte Datei ein und setzt die Variable intern, ohne Klartext-Sichtbarkeit.
5Muss die Anwendung angepasst werden?
Ja, sofern kein nativer _FILE Support existiert, meist reicht eine einfache Dateileseoperation.
6Wo werden Secrets gespeichert?
Unter /run/secrets/<name>, read-only, nur waehrend der Container-Laufzeit vorhanden.
7Wie verhindere ich versehentliches Einchecken?
.gitignore fuer das secrets Verzeichnis, Vorlage mit Platzhaltern, plus gitleaks oder trufflehog in CI.
8Funktionieren Secrets ohne Swarm?
file basierte Secrets ja, external Secrets setzen meist Swarm voraus.
9Kann ich Secrets rotieren ohne Neustart?
Nein, dafuer ist docker compose up -d --force-recreate noetig, um die Datei neu zu mounten.
10Sind .env Dateien dasselbe wie Secrets?
Nein, .env fuellt normale Umgebungsvariablen, genauso sichtbar wie environment direkt.