← Zurueck zu Education
🐳

Docker Grundlagen

Container-Technologie verstehen. Die Basis fuer modernes Self-Hosting.

⏱️ 25-30 Minuten 📊 Einfach
🐳 Was ist Docker? +

Docker ist eine Plattform für Container. Container sind isolierte Umgebungen, die alles enthalten was eine Anwendung braucht - Code, Bibliotheken, Konfiguration.

❌ Ohne Docker

  • "Funktioniert auf meinem PC nicht"
  • Abhängigkeits-Konflikte
  • Unterschiedliche Versionen
  • Komplizierte Installation

✅ Mit Docker

  • Läuft überall gleich
  • Isolierte Umgebungen
  • Einfach reproduzierbar
  • Ein Befehl zum Starten
💡

Container vs VM

Container teilen sich den Kernel des Host-Systems und sind daher viel leichter als VMs. Eine VM braucht ein ganzes Betriebssystem, ein Container nur die Anwendung.

📚 Die wichtigsten Konzepte +

📦 Image

Eine unveränderliche Vorlage für Container. Enthält das Betriebssystem, die Anwendung und alle Abhängigkeiten. Wird von Docker Hub oder anderen Registries heruntergeladen.

Beispiel: nginx:latest, postgres:15-alpine, node:20

🏃 Container

Eine laufende Instanz eines Images. Kann gestartet, gestoppt und gelöscht werden. Änderungen im Container gehen beim Löschen verloren (außer Volumes).

docker run nginx → Startet einen nginx Container

💾 Volume

Persistenter Speicher für Container. Daten in Volumes überleben Container-Neustarts und -Löschungen. Essentiell für Datenbanken, Uploads, Konfigurationen.

-v postgres_data:/var/lib/postgresql/data

🌐 Network

Virtuelle Netzwerke für Container. Container im gleichen Netzwerk können sich über Namen erreichen. Isoliert Container voneinander oder verbindet sie.

Container "app" erreicht "db" über: postgres://db:5432

📝 Docker Compose +

Docker Compose definiert Multi-Container-Anwendungen in einer YAML-Datei. Statt vieler langer Befehle: Eine Datei, ein Befehl.

docker-compose.yml
yaml

version: '3.8'

services:
  # Web-Anwendung
  app:
    image: nginx:alpine
    ports:
      - "80:80"           # Host:Container
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - db
    networks:
      - app-network

  # Datenbank
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: geheim
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - app-network

volumes:
  db_data:              # Benanntes Volume

networks:
  app-network:          # Eigenes Netzwerk
    driver: bridge
💡

Compose vs docker run

Ohne Compose müsstest du jeden Container einzeln mit docker run starten und alle Optionen als Flags übergeben. Compose macht das übersichtlicher und reproduzierbar.

⌨️ Die wichtigsten Befehle +

Diese Befehle wirst du täglich nutzen.

Docker Compose Befehle
bash

# Container starten (im Hintergrund)
docker compose up -d

# Container stoppen
docker compose down

# Container neustarten
docker compose restart

# Status anzeigen
docker compose ps

# Logs anzeigen (live)
docker compose logs -f

# Logs eines Services
docker compose logs -f nginx

# Neue Images ziehen
docker compose pull

# Alles neu bauen und starten
docker compose up -d --build

# In Container-Shell
docker compose exec nginx /bin/sh
Docker Basis-Befehle
bash

# Laufende Container anzeigen
docker ps

# Alle Container (auch gestoppte)
docker ps -a

# Images anzeigen
docker images

# Image herunterladen
docker pull nginx:latest

# Container stoppen
docker stop container_name

# Container löschen
docker rm container_name

# Image löschen
docker rmi image_name

# Unbenutzte Ressourcen aufräumen
docker system prune

# Speicherverbrauch
docker system df
💾 Volumes verstehen +

Volumes sind essentiell für persistente Daten. Ohne Volumes gehen alle Daten beim Container-Neustart verloren!

📁 Bind Mount

Verknüpft Host-Verzeichnis mit Container.

./local/path:/container/path

📦 Named Volume

Docker verwaltet den Speicherort.

volume_name:/container/path
Volumes in docker-compose.yml
yaml

services:
  db:
    image: postgres:15
    volumes:
      # Named Volume (empfohlen für Datenbanken)
      - db_data:/var/lib/postgresql/data

      # Bind Mount (für Konfiguration)
      - ./config/postgresql.conf:/etc/postgresql/postgresql.conf

      # Read-only Bind Mount
      - ./secrets:/run/secrets:ro

volumes:
  db_data:   # Muss deklariert werden
⚠️

Backup nicht vergessen!

Named Volumes liegen unter /var/lib/docker/volumes/. Sichere diese regelmäßig! Bei Bind Mounts sicherst du einfach das Host-Verzeichnis.

🌐 Netzwerke verstehen +

Container im gleichen Netzwerk können sich gegenseitig über ihren Service-Namen erreichen.

┌─────────────────────────────────────────────┐
│           Docker Network: app-net           │
│                                             │
│  ┌─────────┐         ┌─────────┐           │
│  │   app   │────────▶│   db    │           │
│  │  :3000  │  db:5432│  :5432  │           │
│  └─────────┘         └─────────┘           │
│       │                                     │
└───────│─────────────────────────────────────┘
        │
        ▼ Port 3000 exposed
   ┌─────────┐
   │  Host   │
   │ :3000   │
   └─────────┘
Netzwerk-Beispiel
yaml

services:
  app:
    image: myapp:latest
    ports:
      - "3000:3000"    # Erreichbar von außen
    environment:
      # Verbindung zur DB über Service-Name!
      DATABASE_URL: postgres://user:pass@db:5432/mydb
    networks:
      - backend

  db:
    image: postgres:15
    # Kein "ports:" → Nur intern erreichbar
    networks:
      - backend

networks:
  backend:
    driver: bridge
💡

Sicherheit durch Netzwerke

Datenbanken sollten keine Ports nach außen freigeben. Nur die App braucht Zugriff - und das klappt über das interne Netzwerk.

🔧 Umgebungsvariablen +

Konfiguriere Container über Environment Variables statt Dateien zu ändern.

Environment in docker-compose.yml
yaml
services:
  app:
    image: myapp:latest
    environment:
      # Direkt in der Compose-Datei
      - NODE_ENV=production
      - DEBUG=false

      # Aus Host-Umgebung
      - API_KEY=${API_KEY}

      # Mit Default-Wert
      - PORT=${PORT:-3000}

    # Oder aus .env Datei
    env_file:
      - .env
      - .env.local
.env
bash

# Beispiel .env Datei
POSTGRES_PASSWORD=supersecret
API_KEY=abc123
DEBUG=true
⚠️

.env nicht committen!

Füge .env zu .gitignore hinzu! Sensible Daten wie Passwörter gehören nicht ins Repository. Nutze .env.example als Vorlage ohne echte Werte.

🔧 Troubleshooting +

Wenn etwas nicht funktioniert - so findest du den Fehler.

Debugging-Befehle
bash

# Container-Logs anzeigen
docker compose logs -f service_name

# In Container-Shell gehen
docker compose exec service_name /bin/sh
# oder mit bash:
docker compose exec service_name /bin/bash

# Container-Details anzeigen
docker inspect container_name

# Ressourcenverbrauch live
docker stats

# Netzwerke anzeigen
docker network ls

# Netzwerk-Details
docker network inspect network_name

# Volumes anzeigen
docker volume ls

# Aufräumen (Vorsicht!)
docker system prune -a

Container startet nicht?

docker compose logs service_name zeigt Fehlermeldungen

Port already in use?

lsof -i :PORT oder anderen Port in Compose wählen

Permission denied?

→ Volume-Berechtigungen prüfen, chown oder chmod

Kein Speicherplatz?

docker system prune räumt unbenutzte Images auf

💡 Best Practices +
🏷️

Immer Tags verwenden

nginx:1.25 statt nginx:latest - so weißt du welche Version läuft

🔐

Keine Passwörter in Compose

Nutze .env Dateien oder Docker Secrets für sensible Daten

💾

Volumes fuer wichtige Daten

Datenbanken, Uploads, Konfigurationen - immer in Volumes speichern

🌐

Eigene Netzwerke nutzen

Isoliere Container-Gruppen in eigenen Netzwerken

♻️

Regelmaessig aufraeumen

docker system prune entfernt unbenutzte Images und Container

Haeufige Fragen

Docker vs Docker Compose - was ist der Unterschied?

Docker verwaltet einzelne Container. Docker Compose orchestriert mehrere Container als Anwendung. Für Self-Hosting nutzt du fast immer Docker Compose.

Wie update ich einen Container?
bash

# Neues Image ziehen
docker compose pull

# Container neu starten mit neuem Image
docker compose up -d

# Optional: Alte Images aufräumen
docker image prune
Wie sichere ich Docker-Daten?

Zwei Dinge sichern:

  • docker-compose.yml - In Git versionieren
  • Volumes - Mit Backup-Tool (Restic, Borg) oder docker run --rm -v volume:/data -v backup:/backup alpine tar czf /backup/data.tar.gz /data
Container startet immer neu - warum?

Prüfe die Logs mit docker compose logs -f. Oft ist es ein Konfigurationsfehler oder fehlende Umgebungsvariable. restart: unless-stopped sorgt dafür, dass Docker den Container immer neu startet.