Zum Hauptinhalt springen
Self-Hosting & Privatsphäre

Docker Compose YAML-Datei erklärt

Doppelte Schlüssel, gemischte Env-Syntax, unquotierte Booleans: Keiner davon wirft einen Fehler. Ein struktureller Überblick über docker-compose.yml mit YAML-Ankern und der docker compose config-Gewohnheit, die Fehler vor dem Deploy abfängt.

Milan Buha5. November 20267 Min. LesezeitRead in English
TeilenXin
Docker Compose YAML-Datei erklärt

Docker Compose YAML-Datei erklärt

Ihre docker-compose.yml lief ohne einen einzigen Fehler durch. Der Stack kam sauber hoch, jeder Container zeigt running. Und trotzdem zieht ein Dienst den falschen Image-Tag — weil ein doppelter Schlüssel weiter unten in der Datei den ersten lautlos überschrieben hat, und YAML davon kein Wort verloren hat.

TL;DR

  • services: ist der einzige Pflicht-Top-Level-Schlüssel einer Compose-Datei; networks:, volumes:, configs: und secrets: sind optionale Deklarationen, zu denen Leute oft greifen, bevor sie sie überhaupt brauchen — laut der offiziellen Compose-Dateireferenz.
  • Die Syntaxfehler, die wirklich zuschlagen — doppelte Schlüssel, gemischte Listen-/Map-Syntax bei environment:, unquotierte Port-Strings — werfen keinen Fehler. Sie machen still und leise das Falsche.
  • YAML-Anker (&) und Aliase (*) lassen Sie einen Block einmal definieren und über mehrere Dienste hinweg wiederverwenden — das entfernt genau den Copy-Paste-Schritt, der die meisten dieser Fehler erst verursacht.
  • Der Top-Level-Schlüssel version: ist in Compose v2 obsolet und sollte komplett gelöscht werden.
  • docker compose config -q validiert die Datei und schlägt laut fehl, bevor up überhaupt läuft — das sollte Gewohnheit sein, kein letzter Ausweg.

Woraus eine Compose-Datei tatsächlich besteht

Eine Compose-Datei hat genau einen Pflicht-Top-Level-Schlüssel: services. Alles andere — networks, volumes, configs, secrets — ist eine optionale Deklaration, zu der die meisten greifen, bevor sie sie brauchen, weil Tutorials sie nebeneinander zeigen, als wären sie gleich verpflichtend. Das sind sie nicht. Die offizielle Services-Referenz stellt klar, dass unter services die Container tatsächlich definiert werden; der Rest existiert, um von einem Dienst aus referenziert zu werden — nicht, um allein zu stehen.

Diese Unterscheidung ist beim Debuggen wichtig: Schlägt docker compose up mit etwas wie „service must be a mapping" fehl, liegt das Problem fast immer an der Einrückung unter services, nicht an einem fehlenden networks- oder volumes-Block. Fangen Sie dort an, bevor Sie irgendetwas anderes anfassen.

Die Syntaxfehler, die keinen Fehler werfen

Die Fehler, die wirklich einen Abend kosten, sind nicht die, die Compose klar ablehnt — die zeigen Ihnen zumindest eine Zeilennummer. Es sind die, die problemlos parsen und problemlos laufen, nur nicht so, wie Sie es gemeint haben:

Fehler Was passiert Die Lösung
Doppelter Schlüssel im selben Mapping (z. B. ein zweites environment:-Block in einen Dienst eingefügt) Der letzte gewinnt lautlos; der erste wird ohne Warnung verworfen docker compose config laufen lassen und die aufgelöste Ausgabe lesen, nicht die Quelldatei
Listen- und Map-Syntax für environment: im selben Dienst gemischt Compose akzeptiert beide Formen einzeln, aber meldet einen Fehler oder liest falsch, wenn sie kombiniert werden Eine Form (- KEY=value-Liste oder KEY: value-Map) pro Dienst wählen und konsequent bleiben
Unquotiertes Port-Mapping wie 8080:8080 Meist unproblematisch, aber 8080:8080:extra oder ein Wert mit # kann als Kommentar oder Mapping statt als String gelesen werden Port-Strings quotieren: "8080:8080"
yes / no / true / false als nackter Wert YAML-1.1-Parser wandeln das in Booleans um, selbst wenn der literale String gemeint war Quotieren: "yes"
Tabs zur Einrückung YAMLs Spezifikation verbietet Tabs; manche Parser scheitern lautlos, andere melden einen Fehler, dessen Zeilennummer nicht auf den Tab zeigt Nur Leerzeichen, konsequent (2 Leerzeichen ist der De-facto-Standard)

Keiner dieser Fehler erzeugt einen Stack-Trace. Das ist die Gemeinsamkeit — eine Compose-Datei mit einem dieser Fehler sieht für docker compose up exakt aus wie eine korrekte.

Warning: Der Doppelschlüssel-Fehler kostet am wahrscheinlichsten Zeit, weil er still bei einem Copy-Paste-Edit passiert — einen ganzen Dienstblock duplizieren, um einen zweiten zu erstellen, und dann vergessen, einen alten Schlüssel aus dem Original zu entfernen. Nichts in den Logs weist darauf hin. Der einzige Weg, es zu erkennen, ist ein Blick auf die aufgelöste Konfiguration, nicht auf die Datei, die Sie geschrieben haben.

Sich nicht wiederholen: YAML-Anker und Aliase

In meiner eigenen Homelab-Compose-Datei teilten sich früher drei Dienste fast denselben environment:-Block — Zeitzone, Log-Level, ein gemeinsamer DB-Host — jeweils per Copy-Paste eingefügt. Jedes Mal, wenn ich die Zeitzone änderte, musste ich mir drei Stellen merken. Und genau der Doppelschlüssel-Fehler von oben ist mir dabei einmal passiert, als ich einen vierten Dienst einfügte und einen alten Schlüssel übrig ließ.

YAML-Anker lösen das auf Dateiebene, nicht auf Compose-Ebene — sie funktionieren, weil Compose-Dateien reines YAML sind, und eine Anleitung zu Ankern und Extensions in Compose baut auf derselben x--Präfix-Konvention auf, die das Ökosystem für reine Anker-Blöcke verwendet:

x-common-env: &common-env
  TZ: Europe/Berlin
  LOG_LEVEL: info

services:
  app:
    image: myapp:latest
    environment:
      <<: *common-env
      SERVICE_NAME: app

  worker:
    image: myapp-worker:latest
    environment:
      <<: *common-env
      SERVICE_NAME: worker

Der x-common-env-Block wird von Compose selbst ignoriert — jeder Top-Level-Schlüssel, der mit x- beginnt, wird das — und genau deshalb ist es sicher, ihn rein als Anker-Ziel zu nutzen. &common-env benennt den Block; <<: *common-env mischt seine Schlüssel in das environment: jedes Dienstes, und ein lokal definierter Schlüssel (wie SERVICE_NAME) überschreibt den geankerten Wert, falls die Namen kollidieren. Die Zeitzone einmal ändern, an einer Stelle, und beide Dienste übernehmen es.

Note: Die <<-Merge-Key-Syntax ist eine YAML-Extension, kein Teil des strikten YAML-1.2-Kerns — aber der Parser von Compose unterstützt sie, weshalb dieses Muster in docker-compose.yml zuverlässig funktioniert, obwohl manche generischen YAML-Tools sie ablehnen.

Den Schlüssel version: löschen

Beginnt Ihre Compose-Datei noch mit version: "3.8", löschen Sie diese Zeile. In Compose v2 ist das Schema vereinheitlicht und versionslos — der Schlüssel wird ignoriert, und aktuelle Releases drucken eine Deprecation-Warnung, statt den Wert überhaupt noch zu respektieren. Es gibt kein Verhalten, das er noch steuert; ihn zu behalten fügt nur eine Zeile hinzu, die wichtig aussieht und es nicht ist.

Vor dem Deploy validieren: docker compose config

docker compose config rendert die vollständig aufgelöste Konfiguration — jeder Anker expandiert, jedes ${VAR} interpoliert, jede Kurzform ausgeschrieben — ohne einen einzigen Container zu starten. Diese aufgelöste Ausgabe ist das, was tatsächlich an die Docker-Engine geschickt wird, was es zum schnellsten Weg macht, einen doppelten Schlüssel, eine fehlerhafte Interpolation oder einen falsch geschriebenen Dienstnamen zu erkennen, bevor up überhaupt läuft.

Lassen Sie es im Validierungsmodus laufen, der bei Erfolg nichts ausgibt und bei einem Fehler einen echten Fehler zeigt — skriptbar, anders als das Durchsuchen der vollständig gerenderten YAML:

docker compose config -q
echo $?   # 0 = gültig, ungleich 0 = kaputt, mit einer Meldung, die erklärt warum

Für das Anker-Beispiel oben: Bricht man es absichtlich, indem man den Schlüssel SERVICE_NAME im environment:-Block eines Dienstes verdoppelt, parst das trotzdem als gültiges YAML — aber docker compose config (ohne -q) zeigt das zusammengeführte Ergebnis, und der doppelte Schlüssel kollabiert auf den Wert, der zuletzt kam, exakt wie es die Tabelle oben beschreibt. Diese aufgelöste Ausgabe zu lesen ist der Weg, es zu erkennen, bevor der Container jemals mit dem falschen Wert startet.

Tip: Fügen Sie docker compose config -q als Pre-Commit- oder Pre-Deploy-Schritt hinzu, wenn Ihre Compose-Dateien in Git liegen — das kostet unter eine Sekunde und erkennt genau die Fehlerklasse, die sonst zwanzig Minuten später als „warum macht dieser Container das Falsche" auftaucht. Startet der Container, verhält sich aber trotzdem falsch, deckt unser Leitfaden zum Debuggen eines kaputten Compose-Stacks die nächste Ebene darunter ab.

Eine Pre-Deploy-Checkliste

  1. docker compose config -q laufen lassen — Exit-Code 0 bedeutet, die Datei parst und löst zumindest saubere auf.
  2. docker compose config (ohne -q) laufen lassen und nach jedem Wert suchen, der nicht zu dem passt, was Sie in der Quelldatei geschrieben haben — diese Abweichung ist ein doppelter Schlüssel.
  3. Bestätigen, dass oben keine version:-Zeile mehr steht.
  4. Bestätigen, dass jeder environment:-Block in der Datei eine einheitliche Syntax verwendet (Liste oder Map), nicht beide.
  5. Bestätigen, dass Port-Mappings und jeder Wert, der als yes/no/true gelesen werden könnte, quotiert ist.
3eigenständige YAML-Fehler in diesem Leitfaden, die bei docker compose up null Fehlerausgabe produzieren — eigene Messung auf diesem Homelab-Stack

Keiner der drei — doppelte Schlüssel, gemischte Env-Syntax, unquotierte Booleans — scheitert laut. Sie scheitern, indem sie etwas anderes tun als das, was Sie geschrieben haben, was ein schlimmerer Fehlermodus ist, weil Ihnen nichts sagt, dass Sie nachsehen sollen. Sie zu erkennen ist eine Gewohnheit (config vor up laufen lassen), keine einmalige Korrektur. Sobald Ihre Datei sauber validiert, ist unser Leitfaden zu Docker-Compose-Restart-Policies ein sinnvoller nächster Halt — er behandelt, was passiert, wenn ein Container korrekt startet, aber trotzdem ständig stirbt.

FAQ

Wofür wird eine docker-compose.yml-Datei verwendet?

Sie definiert einen oder mehrere Container (services) und wie sie gebaut, konfiguriert und verbunden werden — einschließlich optionaler gemeinsamer networks und persistenter volumes — sodass docker compose up den gesamten Stack aus einer Datei starten kann, statt aus einer langen Folge von docker run-Befehlen.

Warum funktioniert meine docker-compose.yml nicht?

Die meisten Fehler mit einer echten Fehlermeldung weisen auf die Einrückung oder einen fehlenden services-Schlüssel hin. Die Fehler ohne Fehlermeldung — ein doppelter Schlüssel, gemischte environment:-Syntax, ein unquotierter Wert, den Compose als Boolean liest — sind die, nach denen sich speziell lohnt zu suchen, weil der Stack problemlos startet und sich trotzdem falsch verhält.

Wie validiere ich eine docker-compose-Datei vor dem Deployment?

Lassen Sie docker compose config -q laufen. Es löst die vollständige Konfiguration auf — Anker expandiert, Variablen interpoliert — ohne einen Container zu starten, und beendet sich mit einem Fehlercode ungleich null plus Meldung, falls etwas ungültig ist.

Ist der version-Schlüssel in docker-compose.yml erforderlich?

Nein. In Compose v2 ist er obsolet — das Schema ist vereinheitlicht und versionslos, und der Schlüssel wird ignoriert (mit Deprecation-Warnung in aktuellen Releases). Er kann bedenkenlos gelöscht werden.

Kann ich YAML-Anker in einer docker-compose-Datei verwenden?

Ja. Definieren Sie einen Block einmal unter einem mit x- präfixierten Schlüssel (von Compose selbst ignoriert), ankern Sie ihn mit &name, und mischen Sie ihn mit <<: *name in das Mapping jedes beliebigen Dienstes. Das ist der Standardweg, um Konfiguration wie Zeitzone oder Log-Level über Dienste hinweg zu teilen, ohne sie zu kopieren.

Eine Compose-Datei verdient Vertrauen genauso wie jede andere Konfigurationsdatei: indem sie langweilig ist. Tut sie immer nur genau das, was der Quelltext sagt, müssen Sie nicht jedes Mal neu lesen, wenn etwas komisch aussieht. Für das größere Setup, in das das hier passt, siehe unseren Leitfaden zu Docker Compose für Self-Hosting.

Ähnliche Artikel

Mehr aus Self-Hosting & Privatsphäre

Bleiben Sie auf dem Laufenden

Erhalten Sie die neuesten Artikel direkt in Ihr Postfach. Kein Spam, jederzeit abbestellbar.

Als Nächstes lesen

Google Passwort-Manager-PIN: Was sie schützt

Ein neues Smartphone verlangte eine Google Passwort-Manager-PIN, bevor Ihre Logins synchronisierten. Was sie schützt, was nicht, und was bei Verlust der PIN passiert.

Weiterlesen