Warum Docker Compose?
Ich hab am Anfang jeden Container einzeln gestartet. Mit langen docker run Befehlen. Das wurde schnell unübersichtlich.
Docker Compose löst das: Du schreibst alles in eine Datei und startest mit einem Befehl.
docker compose up -d
Fertig. Alle Container laufen, Netzwerke sind erstellt, Volumes angelegt.
Die wichtigsten Befehle
docker compose up -d # Starten
docker compose down # Stoppen
docker compose logs -f # Logs anschauen
docker compose ps # Status
Mehr brauchst du erstmal nicht.
Stack 1: Nginx Webserver
Der einfachste Stack. Gut zum Testen.
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
So nutzt du es:
- Ordner
htmlerstellen - HTML-Dateien reinlegen
docker compose up -d- Browser: http://localhost
Stack 2: WordPress + MySQL
Eine komplette WordPress-Installation. Hab ich für Testseiten genutzt.
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: geheim123
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: wordpress
MYSQL_PASSWORD: geheim123
MYSQL_ROOT_PASSWORD: rootgeheim123
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
wordpress_data:
db_data:
Wichtig: Passwörter ändern. Für Production in eine .env Datei auslagern.
Browser: http://localhost:8080
Stack 3: PostgreSQL + pgAdmin
Für Datenbank-Entwicklung. pgAdmin ist die grafische Oberfläche.
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: geheim123
POSTGRES_DB: development
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
pgadmin:
image: dpage/pgadmin4:latest
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "5050:80"
depends_on:
- postgres
restart: unless-stopped
volumes:
postgres_data:
pgAdmin: http://localhost:5050
Login mit admin@example.com / admin123. Dann Server hinzufügen mit Host postgres.
Fehler, den ich gemacht hab
Ich hab als Host localhost eingetragen. Geht nicht – die Container sind in einem eigenen Netzwerk. Der Hostname ist der Service-Name: postgres.
Stack 4: Traefik Reverse Proxy
Wenn du mehrere Apps hinter einem Port laufen lassen willst. Mit automatischem SSL.
services:
traefik:
image: traefik:v3.0
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=dein@email.de"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
restart: unless-stopped
volumes:
letsencrypt:
Dashboard: http://localhost:8080
Andere Container fügst du mit Labels hinzu:
services:
app:
image: deine-app
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.deinedomain.de`)"
Traefik erkennt das automatisch.
Stack 5: Prometheus + Grafana
Monitoring für mein Homelab. Zeigt CPU, RAM, Disk – alles in Grafana-Dashboards.
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
restart: unless-stopped
grafana:
image: grafana/grafana:latest
environment:
GF_SECURITY_ADMIN_PASSWORD: admin123
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
restart: unless-stopped
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
Du brauchst noch eine prometheus.yml:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
Grafana: http://localhost:3000 (admin/admin123)
Dann Prometheus als Datenquelle hinzufügen: URL = http://prometheus:9090
Tipps aus der Praxis
Secrets in .env Datei
Statt Passwörter in die YAML zu schreiben:
environment:
MYSQL_PASSWORD: ${DB_PASSWORD}
.env Datei:
DB_PASSWORD=sicheres-passwort
Die .env in .gitignore aufnehmen.
Health Checks
Damit Docker weiß, wann ein Container wirklich ready ist:
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Logs debuggen
# Alle Logs
docker compose logs
# Nur ein Service, live
docker compose logs -f wordpress
# Letzte 100 Zeilen
docker compose logs --tail=100
Nächste Schritte
- Kombinieren: Traefik vor WordPress
- Anpassen: Andere Images, mehr Services
- Versionieren: Git-Repo für deine Configs
Tipp: Docker-Befehle üben? In meinen Terminal Missionen gibt’s einen Docker-Track.
Weiterlesen: Docker auf Ubuntu installieren
Bei Fragen: schneider@alexle135.de