SSD Nodes Learn 8GB RAM — $66/Jahr
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-01

Docker Compose: .env, env_file und environment erklärt

Erfahren Sie, wie .env, env_file und environment in Docker Compose funktionieren, welche Einstellung gewinnt und warum Passwörter in Secrets statt Umgebungsvariablen gehören.

Die drei Dinge, die als Env-Datei bezeichnet werden

Docker Compose verfügt über drei separate Mechanismen mit verwirrend ähnlichen Namen. Die Datei .env ersetzt ${VARIABLE}-Platzhalter direkt in compose.yaml, bevor Compose die Datei überhaupt verarbeitet. Das Attribut env_file: lädt eine Datei mit Schlüssel-Wert-Paaren in die Umgebung des Containers. Das Attribut environment: setzt Variablen direkt auf dem Container, die in der Compose-Datei angegeben sind. Diese Mechanismen sind nicht austauschbar. Wenn zwei davon denselben Schlüssel setzen, entscheidet eine dokumentierte Reihenfolge der Priorität.

Dieser Leitfaden zeigt jeden Mechanismus in der Praxis. Er weist die Priorität mit einem ausführbaren Befehl nach. Danach behandelt er den wichtigeren Punkt: Umgebungsvariablen sind für alle lesbar, die docker inspect ausführen können. Passwörter gehören daher nicht in Umgebungsvariablen. Wenn Sie mit Compose-Dateien noch nicht vertraut sind, beginnen Sie mit Docker-Compose-Grundlagen auf einem VPS und kehren Sie anschließend für die Konfiguration hierher zurück.

Die .env-Datei gilt für die Compose-Datei, nicht für den Container

Erstellen Sie ein Verzeichnis und legen Sie zwei Dateien darin ab.

mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .env
services:
  demo:
    image: alpine:${ALPINE_TAG}
    command: printenv ALPINE_TAG

Fragen Sie jetzt Compose, was tatsächlich geparst wurde.

docker compose config

Die Ausgabe zeigt image: alpine:3.20. Der Platzhalter ist verschwunden, weil die Interpolation beim Parsen erfolgt ist. Compose sucht im Projektverzeichnis nach .env. Das ist das Verzeichnis, in dem sich die Compose-Datei befindet. Anschließend ersetzt Compose jedes Vorkommen von ${NAME}.

Starten Sie dann den Dienst.

docker compose run --rm demo

printenv ALPINE_TAG wird mit Status 1 beendet und gibt nichts aus. Die Variable ist im Container nicht vorhanden. Das ist das häufigste Missverständnis: .env hat die Compose-Datei konfiguriert, nicht den Prozess. Eine .env-Datei mit POSTGRES_PASSWORD=hunter2 darin bewirkt für Ihre Datenbank überhaupt nichts, wenn kein Teil der Compose-Datei darauf verweist.

${NAME:-default} stellt einen Fallback bereit, wenn die Variable nicht gesetzt oder leer ist. ${NAME:?message} bewirkt, dass Compose den Start verweigert und Ihre Nachricht ausgibt. Das ist die richtige Wahl für einen Wert ohne sicheren Standardwert.

env_file lädt Variablen in den Container

Das Attribut env_file: benennt eine oder mehrere Dateien. Deren Inhalte werden zu Umgebungsvariablen des Containers.

printf 'GREETING=from_env_file\nAPP_MODE=production\n' > app.env
services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
docker compose run --rm demo

Dies gibt from_env_file aus. Das Dateiformat besteht aus einfachen KEY=value-Zeilen, eine pro Zeile. Ein Kommentar beginnt mit #. Es handelt sich nicht um eine Shell-Datei. Anführungszeichen bleiben in den meisten Fällen Bestandteil des Werts. Präfixe export sind nicht erforderlich. Setzen Sie keine Leerzeichen um das Zeichen =, da KEY = value eine Variable mit dem Namen KEY und einem führenden Leerzeichen im Wert erzeugt.

Ein fehlender Pfad env_file ist ein Fehler, und Compose wird beendet. Kennzeichnen Sie die Datei als optional, wenn sie zulässigerweise fehlen kann:

    env_file:
      - path: ./app.env
        required: false

Umgebung setzt Variablen inline

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    environment:
      GREETING: from_environment

Zwei Syntaxvarianten werden akzeptiert: die obige Zuordnungsform und eine Listenform mit - GREETING=from_environment. Beide verhalten sich identisch. Die Listenform bietet einen zusätzlichen Trick: Ein Schlüssel ohne Wert übernimmt die Variable aus der Shell, in der Sie docker compose ausgeführt haben.

    environment:
      - GREETING
GREETING=from_my_shell docker compose run --rm demo

Das gibt from_my_shell aus. Wenn Sie es ausführen, ohne GREETING in der Shell zu setzen, legt Compose nichts fest und gibt keine Warnung aus. Fehler bei der stillen Weitergabe sollten Sie kennen. Ein Dienst, der mit einer leeren Kennwortvariablen startet, startet häufig erfolgreich und ist dann einfach vollständig ungeschützt.

Welche Einstellung gewinnt

Docker dokumentiert die Rangfolge mit der höchsten Priorität zuerst: docker compose run -e in der Befehlszeile, danach environment oder env_file, deren Wert aus Ihrer Shell oder aus einer env-Datei interpoliert wird, danach das einfache environment in der Compose-Datei, danach env_file und anschließend die in das Image integrierte ENV-Direktive.

Die Kurzfassung für die tägliche Arbeit: environment: hat Vorrang vor env_file:, und -e in der Befehlszeile hat Vorrang vor beiden. Beweisen Sie das in einer Datei.

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
    environment:
      GREETING: from_environment
docker compose run --rm demo
docker compose run --rm -e GREETING=from_cli demo printenv GREETING

Der erste Befehl gibt from_environment aus. Damit hat environment: den Wert in app.env überschrieben. Der zweite Befehl gibt from_cli aus. Nichts in der Compose-Datei überschreibt die Befehlszeile.

Wenn sich ein Container so verhält, als wäre Ihre Konfiguration nie angewendet worden, raten Sie nicht. docker compose config gibt die vollständig aufgelöste Datei aus, und docker compose config --environment gibt die Interpolationsvariablen aus, die Compose verwendet. Bei den meisten Meldungen, dass die env-Datei ignoriert wird, ist ein Wert auf zwei verschiedenen Ebenen doppelt gesetzt.

Warum Umgebungsvariablen offengelegt werden

Legen Sie ein Passwort in environment: fest, wird es in der Containerkonfiguration auf der Festplatte gespeichert. Jeder Benutzer in der Gruppe docker kann es sehen.

docker compose run -d --name leaky -e DB_PASSWORD=hunter2 demo sleep 300
docker inspect leaky --format '{{json .Config.Env}}'

Die Ausgabe enthält "DB_PASSWORD=hunter2" im Klartext. Drei weitere Pfade legen denselben Wert offen. docker compose config gibt ihn im Terminal aus. Dadurch wird er möglicherweise in ein Supportforum kopiert. Jeder Prozess innerhalb des Containers kann /proc/1/environ lesen. Jeder untergeordnete Prozess erbt die Variable. Außerdem schreiben Anwendungsabsturz-Handler routinemäßig die gesamte Umgebung in ein Protokoll oder einen Fehlerbericht.

Die Mitgliedschaft in der Gruppe docker entspricht auf dem Host effektiv root-Rechten. Sie können diese Gruppe daher nicht als Privileggrenze betrachten. Der Leitfaden zu Benutzerkonten mit geringsten Privilegien auf einem VPS erklärt, warum Sie den Zugriff auf diese Gruppe auf gemeinsam genutzten Systemen beschränken sollten.

Compose-Secrets halten den Wert in einer Datei

Compose unterstützt dateibasierte Secrets. Der Wert wird als Datei in den Container eingebunden, statt in die Umgebung injiziert zu werden.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
secrets:
  db_password:
    file: ./db_password.txt

Das Secret wird im Container unter /run/secrets/db_password eingebunden. Der Name nach dem Schrägstrich ist der Secret-Name aus dem Top-Level-Block secrets:.

Das Suffix _FILE ist eine Konvention der Docker Official Images, darunter postgres, mysql und mariadb. Diese EntryPoint-Skripte prüfen auf VARNAME_FILE, lesen die Datei und verwenden ihren Inhalt. Dies ist keine Docker-Funktion. Es funktioniert daher nur, wenn das Image diese Funktion implementiert. Prüfen Sie die Dokumentation des Images, bevor Sie davon ausgehen, dass SOMETHING_FILE berücksichtigt wird. Anwendungen ohne Unterstützung dafür können die Datei beim Start häufig selbst lesen. Alternativ können Sie den Pfad übergeben und dies durch Ihren eigenen EntryPoint erledigen.

Überprüfen Sie dies aus dem laufenden Container heraus:

docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORD

Der erste Befehl gibt das Passwort aus. Der zweite gibt nichts aus, weil der Wert nie in die Umgebung gelangt ist. Genau das ist der Zweck: docker inspect dieses Containers zeigt nur den unkritischen Pfad an.

Schützen Sie die Quelldatei auf dem Host, da das Secret nur so vertraulich ist wie die dahinterliegende Datei:

chmod 600 db_password.txt

Der praktikable Mittelweg auf einem VPS

Viele selbst gehostete Images unterstützen keine _FILE-Variablen. Daher sind Umgebungsvariablen der einzige Weg. Bei einem VPS mit einem einzelnen Administrator besteht das realistische Ziel darin, zu verhindern, dass die Werte in einer für alle lesbaren Datei im Projektverzeichnis liegen. Außerdem dürfen sie nicht in Git landen.

sudo install -o root -g root -m 600 /dev/null /etc/myapp/app.env
sudo nano /etc/myapp/app.env
    env_file:
      - /etc/myapp/app.env

install -m 600 erstellt die Datei bereits mit den richtigen Berechtigungen. Dadurch gibt es kein Zeitfenster, in dem sie für alle lesbar ist. Root ist der Eigentümer. Ein Benutzer ohne Root-Rechte auf dem System kann die Datei daher nicht lesen. Jeder, der docker ausführen darf, kann den Wert jedoch weiterhin aus dem Container auslesen. Fügen Sie *.env und .env zu .gitignore hinzu. Committen Sie stattdessen eine app.env.example, die die Schlüsselnamen mit leeren Werten enthält. Ein committetes Passwort muss geändert werden.

Das Ändern eines Werts bedeutet, den Dienst neu zu starten. Umgebungsvariablen werden einmalig beim Start des Containerprozesses eingelesen. Eine Änderung der Datei hat daher erst Wirkung, wenn Sie docker compose up -d --force-recreate db ausführen. Dasselbe Muster wird im Leitfaden n8n hinter HTTPS auf einem VPS verwendet. Dort liegt der Verschlüsselungsschlüssel außerhalb der Compose-Datei.

Konfiguration nach Umgebung aufteilen

Compose liest .env standardmäßig aus dem Projektverzeichnis. Mit --env-file legen Sie einen anderen Speicherort fest.

docker compose --env-file .env.staging config

Mehrere Dateien werden in der angegebenen Reihenfolge gelesen. Später gelesene Dateien überschreiben frühere. Speichern Sie die nicht geheimen Standardwerte in einer versionierten Datei und die Geheimnisse in einer Datei, die den Server nie verlässt. Dasselbe gilt für env_file:: Bei einem doppelten Schlüssel gilt der Wert aus der zuletzt aufgeführten Datei.

FAQ

Warum wird meine .env-Datei im Container ignoriert?

Sie wird nicht ignoriert. Die Datei .env ersetzt nur ${NAME}-Platzhalter in der Compose-Datei. Sie setzt niemals Variablen innerhalb eines Containers. Damit der Wert in den Container gelangt, verweisen Sie darauf: environment: { KEY: "${NAME}" }, oder verwenden Sie stattdessen env_file: ./that-file.env.

Überschreibt environment env_file, oder ist es umgekehrt?

environment: hat Vorrang. Die dokumentierte Reihenfolge von Docker setzt das Attribut environment über das Attribut env_file. Beide stehen unter docker compose run -e in der Befehlszeile. Wenn ein Schlüssel an beiden Stellen gesetzt ist, wird der Wert in env_file stillschweigend nicht verwendet.

Wie sehe ich den endgültigen Wert, den Compose verwendet?

Führen Sie docker compose config aus, um die vollständig aufgelöste Compose-Datei mit angewandter Interpolation auszugeben. Für einen bereits laufenden Container zeigt docker inspect <container> --format '{{json .Config.Env}}' genau, was dessen Prozess erhalten hat.

Werden Compose-Secrets verschlüsselt?

Nein. Ein dateibasiertes Secret wird als Klartextdatei unter /run/secrets/<name> in den Container eingebunden. Die Quelldatei liegt unverschlüsselt auf der Festplatte des Hosts. Der Vorteil ist die Begrenzung des Gültigkeitsbereichs, nicht die Verschlüsselung: Der Wert bleibt außerhalb der Container-Umgebung, außerhalb der Ausgabe von docker inspect und außerhalb von Crash-Dumps, die die Umgebung ausgeben.

Kann ich Anführungszeichen und Leerzeichen in einer env-Datei verwenden?

Verwenden Sie KEY=value with spaces und lassen Sie die Anführungszeichen weg. Compose behandelt den gesamten restlichen Inhalt der Zeile als Wert. Daher werden Anführungszeichen normalerweise zu wörtlichen Zeichen im Wert. Setzen Sie niemals Leerzeichen um =, da der Schlüssel dann ein nachgestelltes Leerzeichen enthält und keine Übereinstimmung gefunden wird.