fakessh.eu
fakessh.eu
Drei identische schwarze Mini-Servergehäuse stehen nebeneinander auf einem Stahlregal und sind mit kurzen blauen Netzwerkkabeln an einen gemeinsamen Switch angeschlossen.

Docker Compose Grundlagen: compose.yaml, Befehle und typische Fehler

aktualisiert 30. Oktober 2026

ZUSAMMENFASSUNGDocker Compose beschreibt eine Anwendung aus mehreren Containern in einer YAML-Datei (compose.yaml) und startet sie mit docker compose up -d. In der Datei stehen Dienste, Ports, Volumes, Netzwerke und Variablen. Aktuell sind Compose V2 und V5, aufgerufen ohne Bindestrich.

Docker Compose beschreibt eine Anwendung aus mehreren Containern in einer einzigen YAML-Datei und startet, stoppt und überwacht alle Teile mit einem Befehl. Typisch ist eine Webanwendung mit Datenbank: Die Datei compose.yaml legt Images, Ports, Speicher und Netzwerk fest, docker compose up -d startet alles im Hintergrund. Nachfolgend stehen der Aufbau der Datei, ein lauffähiges Beispiel, die wichtigsten Befehle und die häufigsten Fehler.

Zuerst zur Schreibweise des Befehls. Laut der Versionsgeschichte in der Docker-Dokumentation erschien Compose V1 im Jahr 2014, ist in Python geschrieben und heißt docker-compose. Die heutigen Versionen V2 und V5 sind in Go geschrieben und laufen als docker compose ohne Bindestrich, wobei V5 funktional mit V2 identisch ist. Docker erklärte V1 im April 2022 für veraltet und entfernte es mit Docker Desktop 4.23.0 vom 11. September 2023, weil es keine Updates mehr erhielt.

Wann sich Docker Compose lohnt

Die Dokumentation nennt drei typische Einsatzfelder: Entwicklungsumgebungen, automatisierte Tests und Einzelhost-Deployments. Compose ersetzt eine mehrseitige Einrichtungsanleitung durch eine Datei und wenige Befehle. Für Tests entsteht die Umgebung mit docker compose up -d, nach dem Testlauf räumt docker compose down sie ab. Auf einem einzelnen Server ist auch Produktivbetrieb möglich, etwa auf einem eigenen VPS. Ändert sich ein Dienst nicht, verwendet Compose beim nächsten Start den vorhandenen Container weiter.

Docker Desktop bringt Compose mit. Unter Linux mit reiner Docker Engine kommt das Plugin aus dem Docker-Repository: sudo apt-get install docker-compose-plugin unter Debian und Ubuntu, sudo yum install docker-compose-plugin bei RPM-Distributionen. Ob es klappt, zeigt docker compose version.

Aufbau der compose.yaml

Compose und die Compose Specification bevorzugen den Dateinamen compose.yaml, erlaubt ist auch compose.yml. Aus Kompatibilitätsgründen werden zudem docker-compose.yaml und docker-compose.yml gelesen, bei mehreren Dateien gewinnt compose.yaml. Die alte Zeile version: ist obsolet und löst nur eine Warnung aus.

SchlüsselBedeutung
servicesPflichtelement. Jeder Eintrag ist ein Dienst, der aus einem oder mehreren identisch erzeugten Containern besteht.
image, buildFertiges Image aus einer Registry oder ein aus dem eigenen Dockerfile gebautes.
portsVeröffentlicht Containerports auf dem Host in der Form [HOST:]CONTAINER. Ohne Host-IP gilt 0.0.0.0, also alle Schnittstellen. Zahlenpaare stehen in Anführungszeichen, sonst droht eine Verwechslung mit YAML-Zahlen.
volumesBenanntes Volume oder Bind-Mount eines Host-Pfads. Benannte Volumes müssen zusätzlich auf oberster Ebene deklariert werden.
networksOhne Angabe legt Compose ein Netzwerk namens <Projektname>_default an. Der Projektname ist standardmäßig der Verzeichnisname.
environment, env_fileUmgebungsvariablen im Container, direkt oder aus einer Datei.
depends_onReihenfolge beim Starten und Entfernen der Dienste.

Die Dienste erreichen einander über ihren Namen, denn Compose trägt jeden Dienstnamen in einen internen DNS-Server ein. IP-Adressen eignen sich nicht, weil Docker sie bei jedem Start neu vergibt.

Beispiel: WordPress mit MariaDB

Das Beispiel kombiniert die Images wordpress und mariadb. Der Healthcheck folgt der Vorlage aus der MariaDB-Dokumentation. In ein leeres Verzeichnis kommen zwei Dateien, zuerst compose.yaml:

services:
  wordpress:
    image: wordpress
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: ${DB_NAME}
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - wp-data:/var/www/html
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mariadb:lts
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: ${DB_NAME}
      MARIADB_USER: ${DB_USER}
      MARIADB_PASSWORD: ${DB_PASSWORD}
      MARIADB_RANDOM_ROOT_PASSWORD: "1"
    volumes:
      - db-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      start_period: 10s
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  wp-data:
  db-data:

Daneben liegt die Datei .env mit eigenen Werten:

DB_NAME=wordpress
DB_USER=wpuser
DB_PASSWORD=ein-langes-zufaelliges-passwort
  1. docker compose config zeigt die fertig aufgelöste Konfiguration mit eingesetzten Variablen.
  2. docker compose up -d lädt die Images und startet zuerst db. wordpress folgt, sobald der Healthcheck besteht.
  3. docker compose ps listet Status und Ports. Danach ist WordPress unter http://localhost:8080 erreichbar.

WORDPRESS_DB_HOST: db verweist auf den Dienstnamen. Der Eintrag 127.0.0.1:8080:80 macht den Port nur auf dem Host selbst erreichbar. MARIADB_DATABASE legt die Datenbank beim ersten Start an, denn der WordPress-Container erzeugt sie nicht selbst. Das zufällige Root-Passwort steht im Log von db.

Docker rät, Passwörter nicht als Umgebungsvariablen zu übergeben, sondern als Secrets. Das MariaDB-Image unterstützt dafür Variablen mit der Endung _FILE. Die .env mit echten Passwörtern gehört nicht ins Git-Repository.

Die wichtigsten Befehle

BefehlWirkung
docker compose up -dErstellt und startet alle Dienste im Hintergrund. Geänderte Dienste werden neu erstellt, gemountete Volumes bleiben erhalten.
docker compose psZeigt laufende Container des Projekts mit Status und Ports, mit --all auch gestoppte.
docker compose logs -f dbVerfolgt die Logausgabe fortlaufend. Ohne Dienstnamen erscheinen alle Dienste.
docker compose downStoppt und entfernt Container und Netzwerke. Benannte Volumes bleiben bestehen.
docker compose down -vEntfernt zusätzlich die Volumes aus dem Abschnitt volumes und löscht damit die gespeicherten Daten.

Variablen und .env

Compose liest die Datei .env im Projektverzeichnis automatisch und setzt ihre Werte an Platzhaltern wie ${DB_PASSWORD} ein. In den Container gelangt ein Wert dadurch noch nicht, dafür sorgen environment oder env_file. Bei gleichen Namen gewinnt die Shell-Umgebung vor --env-file, und dieses vor der .env. Mit ${VAR:-standard} lässt sich ein Standardwert vorgeben, ${VAR:?Fehlertext} bricht ab, wenn die Variable fehlt oder leer ist. Ein wörtliches Dollarzeichen schreibt man in der compose.yaml als $$.

Typische Fehler

SymptomUrsache und Abhilfe
Anwendung startet, erreicht die Datenbank aber nichtdepends_on in der Kurzform wartet nur auf den Start des Containers, nicht auf seine Bereitschaft. MariaDB nimmt während der Initialisierung keine Verbindungen an. Abhilfe: Healthcheck plus condition: service_healthy.
Port ist im Internet offen, obwohl ufw ihn sperrtDocker leitet veröffentlichte Ports vor den ufw-Regeln um. Mit 127.0.0.1:8080:80 veröffentlichen und einen Reverse-Proxy vorschalten.
Verbindung zwischen Containern scheitertZwischen Containern zählt der Containerport. Bei "8001:5432" spricht die Anwendung db:5432 an, nicht Port 8001.
Warnung „variable is not set“Compose setzt dann einen leeren String ein. Meist fehlt die .env oder liegt im falschen Verzeichnis. Ein $ im Passwort verlangt einfache Anführungszeichen in der .env.
Daten nach dem Neustart wegEntweder war es down -v, oder das Volume hängt am falschen Pfad. Das PostgreSQL-Image erwartet ab Version 18 den Pfad /var/lib/postgresql, bis Version 17 den Pfad /var/lib/postgresql/data.
Neues Datenbankpasswort wirkt nichtDas MariaDB-Image wertet seine Variablen nur bei leerem Datenverzeichnis aus. Bei vorhandener Datenbank das Passwort in der Datenbank ändern.
Bind-Mount verhält sich unerwartetVerzeichnis und Rechte auf dem Host müssen stimmen. Ein Bind-Mount verdeckt vorhandene Dateien im Container-Verzeichnis. Auf SELinux-Systemen gibt es die Optionen :z und :Z.

Häufige Fragen

Was ist Docker Compose?

Docker Compose ist ein Werkzeug, das Anwendungen aus mehreren Containern in einer YAML-Datei beschreibt. Ein Befehl wie docker compose up -d erstellt und startet alle Dienste, Netzwerke und Volumes.

Was ist der Unterschied zwischen docker-compose und docker compose?

docker-compose ist Compose V1, 2014 in Python geschrieben und ohne Updates. Aktuell sind V2 und V5, aufgerufen als docker compose ohne Bindestrich. Unter Linux kommt es als Plugin docker-compose-plugin.

Wie heißt die Compose-Datei?

Bevorzugt compose.yaml, möglich ist auch compose.yml. Aus Kompatibilitätsgründen liest Compose außerdem docker-compose.yaml und docker-compose.yml. Gibt es mehrere, hat compose.yaml Vorrang.

Wie lässt sich die Startreihenfolge der Dienste steuern?

Mit depends_on. In der Kurzform wartet Compose nur, bis der andere Container gestartet ist. Für Bereitschaft braucht der Dienst einen healthcheck und die Bedingung service_healthy.

Löscht docker compose down die Daten?

Nicht standardmäßig: down entfernt Container und Netzwerke, benannte Volumes bleiben erhalten. Erst docker compose down -v löscht die benannten Volumes und damit die darin gespeicherten Daten.

Weitere Anleitungen

SSH-Schlüssel erstellen mit ssh-keygen: Ed25519, Passphrase und Server-Zugang

SSH-Schlüssel erstellen mit ssh-keygen: Ed25519, ECDSA oder RSA, Passphrase, ssh-agent, Kopie auf den Server, Dateirechte sowie Windows und macOS.