Docker Compose für Einsteiger: Dein erstes Self-Hosted-Setup in 30 Minuten
Vom leeren Server zum laufenden Stack: Dieses Tutorial führt dich Schritt für Schritt durch dein erstes Docker-Compose-Setup – inklusive Netzwerk, Volumes, Updates und der einen Regel, die dich später vor bösen Überraschungen bewahrt.
Was ist Docker Compose – und warum brauchst du es?
Docker allein startet einzelne Container. Eine moderne Anwendung besteht aber fast nie aus nur einem
Teil: Nextcloud braucht eine Datenbank, ein Reverse Proxy braucht die App-Container, Monitoring braucht
gleich ein halbes Dutzend Dienste. Jeden Container einzeln per docker run mit Dutzenden
Flags zu starten, ist fehleranfällig und nicht reproduzierbar.
Docker Compose löst das: Du beschreibst den kompletten Stack – Images, Ports, Volumes,
Umgebungsvariablen und Abhängigkeiten – in einer einzigen docker-compose.yml. Ein Befehl
startet alles, ein zweiter stoppt alles, und weil die Datei als Text vorliegt, kannst du sie versionieren,
teilen und auf jedem Server reproduzieren. Genau deshalb ist Compose der Standard fürs Self-Hosting.
Vorbereitung: Server & Docker installieren
Du brauchst einen Linux-Server (Debian oder Ubuntu funktionieren am besten), Zugriff per SSH und einen
Benutzer mit sudo-Rechten. Als Einstieg reicht ein VPS im Free Tier oder ein Raspberry Pi –
mehr dazu findest du in unserem Beitrag „Wo hosten ohne Geld?“.
Docker Engine inklusive Compose-Plugin installierst du auf Debian/Ubuntu so:
# System aktualisieren
sudo apt update && sudo apt upgrade -y
# Offizielles Docker-Installationsskript (prüfbar unter get.docker.com)
curl -fsSL https://get.docker.com | sh
# Benutzer in die Docker-Gruppe aufnehmen (danach neu einloggen)
sudo usermod -aG docker $USER
# Installation prüfen – Compose ist als Plugin enthalten
docker --version
docker compose version
💡 Tipp: Nicht jedes docker-compose-Kommando in alten Tutorials
funktioniert mit dem aktuellen Plugin. Moderne Syntax ist docker compose (mit Leerzeichen).
Seit Docker 2023 ist das Plugin bei der Installation enthalten.
Deine erste docker-compose.yml
Als Praxisbeispiel starten wir Uptime Kuma – ein Open-Source-Monitoring-Tool, das Websites überwacht und dich bei Ausfällen benachrichtigt. Dazu legen wir ein Projektverzeichnis an und schreiben die Compose-Datei:
mkdir -p ~/uptime-kuma && cd ~/uptime-kuma
nano docker-compose.yml
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: unless-stopped
volumes:
- ./data:/app/data
ports:
- "127.0.0.1:3001:3001"
Zeile für Zeile bedeutet das:
image– welches Image gestartet wird (hier das offizielle von louislam).restart: unless-stopped– der Container startet nach Neustarts und Abstürzen automatisch wieder.volumes– der Ordner./dataauf dem Host wird ins Verzeichnis/app/dataim Container gemountet. Dort liegen alle deine Daten.ports– bindet Port 3001 des Containers an deinen Server – aber bewusst nur an127.0.0.1(dazu unten mehr).
Start, Logs & Co. – die wichtigsten Befehle
Diese fünf Befehle decken 95 % des Alltags ab:
# Stack starten (im Hintergrund, mit -d)
docker compose up -d
# Status der Container anzeigen
docker compose ps
# Logs live verfolgen
docker compose logs -f
# Alles stoppen (Container bleiben erhalten)
docker compose down
# Alles stoppen UND Daten-Volumes löschen – Vorsicht!
docker compose down -v
⚠️ Achtung: docker compose down -v löscht benannte Volumes und damit
alle Daten deiner Dienste. Diese Flagge ist kein Aufräum-Tool für den Alltag –
sie wird vor allem dann gebraucht, wenn du einen Stack von Grund auf neu aufsetzen willst.
Volumes, Netzwerke & der berühmte Port-Fehler
Container sind Wegwerf-Objekte: Wird einer ersetzt, ist alles verloren, was nicht in einem Volume liegt.
Faustregel: Jeder Dienst schreibt seine Daten nur in Volumes oder gemountete Ordner.
Wir haben mit ./data ein sogenanntes Bind Mount verwendet – das liegt direkt in
deinem Projektordner und ist damit einfach zu sichern.
Und jetzt die versprochene Regel: Binde Container-Ports niemals an 0.0.0.0.
Dahinter verbirgt sich die wichtigste Lehre aus tausenden gehackten Heimservern:
"3001:3001"→ Der Dienst ist weltweit unter Port 3001 erreichbar. Ohne Passwortschutz ist er in Minuten Ziel von Bots."127.0.0.1:3001:3001"→ Der Dienst lauscht nur lokal und ist ausschließlich über deinen Reverse Proxy erreichbar – verschlüsselt per HTTPS und mit zentralem Auth.
Genau dafür steht vor dem Port der 127.0.0.1:-Prefix. Der Reverse Proxy – bei uns im
großen Proxy-Vergleich getestet – läuft im selben Docker-Netzwerk
und spricht die Dienste intern über den Containernamen an, ganz ohne öffentliche Ports.
Braucht ein Dienst mit mehreren Containern ein internes Netzwerk (z. B. App + Datenbank), legst du es einfach an – Compose erstellt pro Projekt automatisch ein eigenes Netzwerk, in dem sich Container über ihren Dienstnamen erreichen:
services:
app:
image: beispiel/app
networks: [intern]
db:
image: postgres:17
networks: [intern]
networks:
intern:
Updates ohne Datenverlust
Ein sauberes Update ist in Compose ein Dreizeiler – die Volumes bleiben dabei unangetastet:
cd ~/uptime-kuma
# Neue Images ziehen
docker compose pull
# Container mit neuer Konfiguration neu erstellen
docker compose up -d
# Nicht mehr benötigte Images aufräumen
docker image prune -f
Vor jedem Update gilt: Backup zuerst. Für Dienste mit Datenbanken reicht ein Datei-Backup oft nicht – die Datenbank muss konsistent gesichert werden. Wie das richtig geht, zeigen wir im Nextcloud-Artikel.
Fazit & nächste Schritte
Mit einer docker-compose.yml kannst du in 30 Minuten den ersten Dienst dauerhaft und
wartbar betreiben. Die vier Grundpfeiler sind: Volumes für Daten, nur lokale Port-Bindings,
ein Reverse Proxy nach außen und Backups vor jedem Update. Wenn diese sitzen, ist dir fast
jeder Dienst der Self-Hosting-Welt zugänglich.
✅ Zum Mitnehmen: (1) Compose-Datei = komplette Beschreibung des Stacks.
(2) Daten immer in Volumes, nie im Container. (3) Dienste nur an 127.0.0.1 binden,
nie an 0.0.0.0. (4) Updates laufen über pull + up -d.
(5) down -v löscht Daten – nur bewusst verwenden.