
Im letzten Artikel haben wir uns angesehen, wie Docker unter der Haube funktioniert. Wir haben gelernt, was Images sind, wie der Daemon arbeitet und wie man einen einzelnen Container startet.
Aber mal ehrlich: Moderne Webanwendungen sind selten Einzelgänger.
Eine typische App besteht oft aus einem Frontend, einem Backend-Service, einer Datenbank wie PostgreSQL und vielleicht noch einem Caching-Layer wie Redis. Wenn du versuchst, das alles mit einzelnen docker run-Befehlen im Terminal zu jonglieren, verlierst du schnell den Überblick. Du müsstest Netzwerke manuell anlegen, IP-Adressen verwalten und die Startreihenfolge beachten.
Genau hier kommt Docker Compose ins Spiel.
Docker Compose ist ein Tool für Multi-Container-Anwendungen. Wenn das Dockerfile das Rezept für eine einzelne Komponente ist (zum Beispiel den Kuchen), dann ist Docker Compose die Speisekarte für das gesamte 3-Gänge-Menü.
Mit einer einzigen Datei, der docker-compose.yml, beschreibst du deine komplette Infrastruktur. Das Geniale: Du kannst deine gesamte Umgebung mit einem einzigen Befehl hochfahren.
Warum ist das gerade für Selfhosting wichtig?
Wenn du auf einem VPS deine eigenen Services hosten willst, brauchst du eine Lösung, die mehrere Container gleichzeitig verwaltet. Ohne Docker Compose wird das schnell unübersichtlich. Mit Docker Compose hast du alles im Griff. Eal ob du Nextcloud, GitLab oder eine WordPress-Instanz betreibst.
Docker Compose nutzt YAML. Das ist ein Format, welches sowohl für Menschen als auch für Maschinen gut lesbar ist. Schauen wir uns die wichtigsten Bausteine an.
Unter services definierst du die Container, die laufen sollen. Jeder Service bekommt einen Namen (zum Beispiel web oder db), den du später auch für die interne Kommunikation nutzen kannst.
Früher war die Vernetzung von Containern kompliziert. Mit Docker Compose ist sie fast schon magisch. Services im gleichen Netzwerk können sich gegenseitig über ihren Service-Namen erreichen. Du musst keine IP-Adressen mehr hardcoden. Dein Backend ruft einfach db:5432 auf, und Docker leitet es an den Datenbank-Container weiter.
Container sind vergänglich. Wenn du einen Datenbank-Container löschst, sind die Daten weg. Außer du nutzt Volumes. In der Compose-Datei definierst du, wo Daten persistent auf deinem Host-System gespeichert werden.
Hier ist ein praktisches Beispiel für ein Setup mit Web-App und Datenbank:
version: '3.8'
services:
webapp:
build: ./app
ports:
- '8080:80'
depends_on:
- database
environment:
- DB_HOST=database
- DB_USER=${DB_USER}
- DB_PASS=${DB_PASSWORD}
restart: unless-stopped
database:
image: postgres:15-alpine
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
restart: unless-stopped
volumes:
db_data:
Hinweis: Die Variablen wie ${DB_USER} sind Umgebungsvariablen. Dazu gleich mehr.
Docker Compose macht deinen Workflow extrem effizient. Statt langer Shell-Scripte brauchst du nur eine Handvoll Befehle:
Container starten:
docker-compose up -d
Dieser Befehl liest deine Konfiguration, lädt die nötigen Images, erstellt Netzwerke und startet alle Container im Hintergrund (-d für detached).
Status checken:
docker-compose ps
Zeigt dir sofort, welche Services laufen, welche Ports belegt sind und ob ein Container abgestürzt ist.
Logs ansehen:
docker-compose logs -f
Wichtig fürs Debugging. Hiermit siehst du die Log-Ausgaben aller Services gebündelt in einem Stream.
Container stoppen:
docker-compose down
Stoppt die Container und räumt die Netzwerke auf. Sauber und ordentlich.
Container neu bauen:
docker-compose up -d --build
Wenn du Änderungen am Code gemacht hast, baut dieser Befehl die Images neu und startet die Container.
Im Code-Beispiel oben haben wir ${DB_PASSWORD} verwendet. Hardcodierte Passwörter in einer yml-Datei sind ein Sicherheitsrisiko – besonders wenn du den Code auf GitHub pushst.
Docker Compose unterstützt .env-Dateien automatisch. Leg eine Datei namens .env im gleichen Ordner an und pflege die Variablen:
DB_USER=admin
DB_PASSWORD=supergeheim
Wichtig für die Sicherheit:
.env zu deiner .gitignore hinzuWarum ist Docker Compose perfekt für Selfhosting?
1. Einfaches Setup auf einem VPS
Du loggst dich per SSH auf deinen Hetzner-Server ein, lädst deine docker-compose.yml hoch und startest mit einem Befehl deine komplette Infrastruktur.
2. Reproduzierbare Umgebungen Deine lokale Entwicklung sieht genauso aus wie dein Produktionsserver. Kein "Auf meinem Rechner läuft es aber!"-Problem mehr.
3. Einfache Updates
Neue Version deiner App? Ändere das Image-Tag in der docker-compose.yml, führe docker-compose pull und docker-compose up -d aus – fertig.
4. Ressourcen-Effizienz Auf einem VPS mit 4GB RAM kannst du locker 5-10 kleinere Services gleichzeitig hosten, dank der schlanken Container-Architektur.
Hier ein komplettes Beispiel, wie du WordPress selbst hosten kannst:
version: '3.8'
services:
wordpress:
image: wordpress:latest
ports:
- '80:80'
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
depends_on:
- db
restart: unless-stopped
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
wordpress_data:
db_data:
So startest du es auf deinem Server:
# Docker Compose Datei hochladen
scp docker-compose.yml root@dein-server.de:/opt/wordpress/
# Auf dem Server
ssh root@dein-server.de
cd /opt/wordpress
echo "DB_USER=wpuser" > .env
echo "DB_PASSWORD=sicheres-passwort" >> .env
echo "DB_ROOT_PASSWORD=noch-sichereres-passwort" >> .env
# Starten
docker-compose up -d
Problem: Container startet nicht
docker-compose logs service-name
Schau dir die Logs an. Meist fehlt eine Umgebungsvariable oder ein Volume-Pfad existiert nicht.
Problem: Port schon belegt
Ändere in der docker-compose.yml den Port links vom Doppelpunkt: "8080:80" statt "80:80"
Problem: Container kann nicht auf andere Services zugreifen Prüfe, ob alle Services im gleichen Netzwerk sind und ob die Service-Namen richtig geschrieben sind.
restart: unless-stopped
Damit starten deine Container nach einem Server-Neustart automatischdocker-compose.yml für Entwicklung, docker-compose.prod.yml für Produktion.env-Dateien für lokale Entwicklung und Docker Secrets oder Umgebungsvariablen für ProduktionSo sieht ein typischer Workflow aus:
docker-compose up -d
# Code ändern, testen
docker-compose restart webapp
# Code zum Server pushen (Git, rsync, scp)
ssh user@server
docker-compose pull
docker-compose up -d --build
docker-compose logs -f
docker-compose ps
Docker Compose verwandelt das Chaos einzelner Container in ein gut organisiertes System. Es ist das Tool, das dich vom "Rumspielen mit Docker" zum "Betreiben echter Produktivumgebungen" bringt.
Die wichtigsten Vorteile:
Ob du nun einen Blog, eine Cloud-Speicher-Lösung oder ein Monitoring-System hosten willst, Docker Compose macht es einfach, wartbar und reproduzierbar.
Nächste Schritte:
Möchtest du mehr über Deployment-Strategien und Selfhosting erfahren? Schau dir unsere Hosting-Lösungen auf lowcloud.io an – optimiert für Docker und moderne Container-Workflows.
n8n selbst hosten: Workflow-Automatisierung auf deinem VPS
Lerne, wie du n8n mit Docker selbst hostest. Ein komplettes Schritt-für-Schritt-Tutorial, um Kosten zu sparen, Datensouveränität zu gewährleisten und Workflow-Automatisierung zu meistern.
Docmost selbst hosten mit Docker Compose und Traefik: Komplette Anleitung
Erfahre, wie du Docmost auf deinem eigenen Server mit Docker Compose und Traefik als Reverse Proxy selbst hostest. Eine Schritt-für-Schritt-Anleitung für DSGVO-konforme Dokumentation.