Docker Compose: env_file, environment und .env, was macht was?
Leitfaden zu Docker Compose env_file
Docker Compose: env_file, environment und .env im Vergleich | We.Inc
Was env_file, environment und die .env-Datei in Docker Compose jeweils tun, welcher Wert bei Konflikten gewinnt und wie die Interpolation mit ${VAR:-default} funktioniert, mit Resolver.
In Docker Compose lädt env_file eine Datei mit KEY=value-Zeilen in den Container eines einzelnen Service. Das Attribut environment setzt Container-Variablen direkt in der Datei und schlägt env_file, wenn beide denselben Schlüssel nennen. Die .env-Datei neben compose.yaml ist etwas anderes: Compose liest sie, um ${VAR}-Platzhalter im YAML selbst zu füllen.
Drei Wege, Compose mit Variablen zu versorgen
Mechanismus
Geltungsbereich
Landet im Container?
.env neben compose.yaml
Interpolation von ${VAR} in der Compose-Datei
Nur wenn ein Service darauf verweist
env_file: an einem Service
Der Container dieses Service
Ja, jede Zeile
environment: an einem Service
Der Container dieses Service
Ja, und es schlägt env_file
--env-file in der CLI
Ersetzt die Standard-.env für die Interpolation
Nur wenn referenziert
Die Verwirrung kommt vom Namen: Eine Datei namens .env und ein Attribut namens env_file klingen nach demselben, aber das eine konfiguriert die Compose-Datei und das andere einen Container. Prüfe mit dem Resolver, welche Quelle für eine Variable gewinnt, und teste dann die Interpolationsformen mit einer gesetzten, leeren oder nicht gesetzten Variable.
Hake jede Stelle an, an der deine Variable gesetzt ist, und gib den Wert ein, den sie dort hat.
Der Resolver geht Dockers dokumentierte Rangfolge von oben durch und zeigt, welchen Wert der Container am Ende bekommt.
Wähle im Interpolationsfeld eine Form wie ${VAR:-default}, lege fest, ob VAR gesetzt, leer oder nicht gesetzt ist, und lies das Ergebnis ab.
Führe docker compose config in deinem Projekt aus, um zu prüfen, was Compose tatsächlich aufgelöst hat.
Führe docker compose config --environment aus, um die Variablen auszugeben, die Compose für die Interpolation verwendet hat. Damit sind die meisten Diskussionen in Sekunden geklärt.
Markiere optionale env-Dateien mit required: false (ab Compose 2.24.0), damit ein fehlender lokaler Override den Stack nicht stoppt.
Schreibe $$, wenn du in compose.yaml ein echtes Dollarzeichen brauchst, zum Beispiel in einem Passwort oder einem Shell-Befehl.
Setze Boolesche Werte in der environment-Map in Anführungszeichen, etwa SHOW: "true", damit YAML sie nicht in true- und false-Werte umwandelt.
Häufige Fragen
Was ist der Unterschied zwischen env_file und environment?
Beide bringen Variablen in den Container eines Service. env_file liest sie aus einer oder mehreren Dateien, environment listet sie in compose.yaml auf. Taucht derselbe Schlüssel in beiden auf, gewinnt der Wert aus environment, selbst wenn er leer ist.
Übergibt Compose meine .env-Datei automatisch an die Container?
Nein. Die .env-Datei des Projekts dient nur dazu, ${VAR} in der Compose-Datei zu ersetzen. Eine Variable landet nur dann in einem Container, wenn ein Service sie unter environment nennt oder die Datei mit env_file lädt.
Wo sucht Compose nach der .env-Datei?
Im Projektverzeichnis, also dem Ordner aus --project-directory, sonst dem Ordner der ersten -f-Datei, sonst deinem aktuellen Ordner. Mit --env-file verweist du auf eine andere Datei; bei mehreren überschreiben spätere Dateien frühere.
Sind env_file-Pfade relativ zu dem Ort, an dem ich den Befehl ausführe?
Nein. Relative Pfade in env_file werden vom Ordner aus aufgelöst, in dem die Compose-Datei liegt, sodass der Stack funktioniert, egal von wo du ihn startest.
Was passiert mit ${VAR}, wenn VAR nicht gesetzt ist?
Compose gibt eine Warnung aus und setzt einen leeren String ein. Mit ${VAR:-fallback} gibst du einen Standardwert vor, mit ${VAR:?message} brichst du stattdessen mit einem Fehler ab.
Die Rangfolge, von oben nach unten
Docker dokumentiert fünf Ebenen. Ein Wert, der mit docker compose run -e übergeben wird, ist am stärksten. Danach folgt environment oder env_file, wenn der Wert aus deiner Shell oder einer Umgebungsdatei interpoliert wird, dann ein literaler Wert unter environment, dann ein Wert aus env_file und zuletzt eine ENV-Zeile, die ins Image eingebaut ist.
Beachte, dass nur eine davon die .env-Datei ist, und das nur indirekt: Sie speist Ebene zwei über die Interpolation. Ein Wert in .env, den kein Service erwähnt, taucht nie in einem Container auf.
Schlüssel ohne Werte
Ein reiner Name unter environment, etwa - API_TOKEN ohne Gleichheitszeichen, übernimmt den Wert aus der Shell, in der Compose läuft. Hat die Shell ihn nicht, bleibt die Variable ungesetzt.
In einer env_file entfernt eine Zeile, die nur einen Schlüssel enthält, diese Variable aus der Container-Umgebung. Das ist praktisch, um gezielt etwas zu löschen, das das Image setzt.
Alle Interpolationsformen
Was jede Form bei gesetzter, leerer oder nicht gesetzter VAR ergibt
Form
VAR=abc
VAR leer
VAR nicht gesetzt
${VAR} or $VAR
leer, mit Warnung
${VAR:-default}
${VAR-default}
${VAR:?msg}
Fehler msg
Fehler msg
${VAR?msg}
Fehler msg
${VAR:+other}
${VAR+other}
ein literales $
ein literales $
ein literales $
Compose-Dateien zum Kopieren
env_file plus Overrides per environment
Gemeinsame Einstellungen kommen aus Dateien; die environment-Einträge gewinnen für die Schlüssel, die sie nennen. Die lokale Datei ist optional.
Projekt-.env nur für die Interpolation
Diese beiden Werte füllen Platzhalter in compose.yaml. Keiner davon landet in einem Container, solange ihn kein Service erwähnt.
Diese Werte in compose.yaml verwenden
Der Image-Tag und der veröffentlichte Port kommen aus .env; das Passwort muss gesetzt sein, sonst stoppt Compose mit einer klaren Meldung.
Prüfen, was Compose aufgelöst hat
config gibt das fertige Modell mit allen eingesetzten Variablen aus; --environment listet die Werte, die für die Ersetzung verwendet wurden.
Welcher Wert gewinnt?
Die Variable APP_MODE ist an den unten angehakten Stellen gesetzt.
Wo die Variable gesetzt ist
Wert
Der Container bekommt APP_MODE={v} aus: {n}
Nirgends gesetzt, daher fehlt APP_MODE im Container.
Interpolations-Tester
Ausdruck
VAR ist
gesetzt, aber leer
Wert von VAR
Ergebnis: {v}
Ergebnis: ein leerer String
Compose stoppt mit dem Fehler: {v}
Ergebnis: ein leerer String, und Compose gibt eine Warnung aus