Files
2026-04-01 13:35:27 +02:00

22 KiB
Raw Permalink Blame History


🐳 Einführung in Docker

1. Was ist Docker?

Docker ist eine Plattform, mit der du Container erstellen, starten und verwalten kannst.
Ein Container ist eine Art "leichtgewichtige virtuelle Maschine":

  • Enthält nur das Nötigste (Programm, Abhängigkeiten, Bibliotheken).
  • Läuft isoliert, aber nutzt den Kernel des Host-Systems (kein eigener Kernel wie bei einer VM).
  • Ist schneller und ressourcenschonender als klassische VMs.

👉 Bildlich: Statt für jedes Programm einen eigenen PC (VM) aufzubauen, packst du nur das Programm in eine "Transportbox" (Container), die überall läuft, solange Docker installiert ist.


2. Vorteile und typische Anwendungsfälle

Vorteile

  • Portabilität: „Läuft auf meinem Rechner“ = „läuft auch auf Servern“.
  • Isolierung: Verschiedene Programme/Versionen stören sich nicht.
  • Leichtgewicht: Start in Sekunden statt Minuten wie bei VMs.
  • Reproduzierbarkeit: Gleiche Umgebung für Entwicklung, Test und Produktion.
  • Einfache Verteilung: Images können über Docker Hub oder private Registries geteilt werden.

Typische Anwendungsfälle

  • 🚀 Entwicklung: Z. B. Python 3.10 testen, obwohl auf dem System Python 3.12 läuft.
  • 🗄️ Datenbanken: MySQL, PostgreSQL, Redis, MongoDB zum Testen ohne Installation.
  • 🌐 Web-Apps: Schnell mal eine fertige Anwendung ausprobieren (WordPress, Nextcloud, GitLab etc.).
  • 🧪 Testing: Mehrere Umgebungen simulieren (verschiedene OS, Bibliotheksversionen).
  • 📦 Deployment: Gleiche App auf mehreren Servern identisch bereitstellen.

3. Hauptfunktionalitäten von Docker

  • Docker Engine: Herzstück, das Container ausführt.
  • Docker Images: Baupläne (Templates) für Container (z. B. Python 3.12 + Flask).
  • Docker Containers: Laufende Instanzen von Images.
  • Docker Hub/Registry: Cloud-Marktplatz für fertige Images.
  • Docker Compose: Orchestrierung mehrerer Container (z. B. App + DB + Cache).

4. Installation unter Linux (Beispiel: Ubuntu/Debian)

# 1. Alte Versionen entfernen
sudo apt-get remove docker docker-engine docker.io containerd runc

# 2. Repository vorbereiten
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg

# Docker GPG-Key hinzufügen
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Repository einrichten
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 3. Docker installieren
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 4. Testen
sudo docker run hello-world

👉 Danach kannst du optional dich in die docker-Gruppe aufnehmen (sonst musst du immer sudo schreiben):

sudo usermod -aG docker $USER
# Abmelden/neu anmelden, damit es wirkt

5. Erste Schritte in der Praxis

Beispiel 1: Linux — Container starten

# Einen Ubuntu-Container starten (interaktiv)
docker run -it ubuntu bash

# Danach bist du im Container:
root@<id>:/# cat /etc/os-release

Wenn du rausgehst (exit), bleibt der Container gespeichert.


Beispiel 2: Linux — Nginx-Webserver starten

# Nginx starten, Port 8080 weiterleiten
docker run -d -p 8080:80 nginx

# Nun im Browser: http://localhost:8080

Beispiel 3: Python im Container

Nehmen wir an, du willst ein Python-Skript in einer isolierten Umgebung ausführen.

hello.py

print("Hello from Dockerized Python!")

Dockerfile

FROM python:3.11-slim

# Skript ins Image kopieren
COPY hello.py /app/hello.py

# Arbeitsverzeichnis setzen
WORKDIR /app

# Default-Befehl
CMD ["python", "hello.py"]

Bauen und starten

# Image bauen
docker build -t mypythonapp .

# Container starten
docker run --rm mypythonapp

Ausgabe:

Hello from Dockerized Python!

Beispiel 4: Python mit externer Bibliothek

# requirements.txt
flask==3.0.0

app.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, Docker!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Dockerfile

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY app.py .

CMD ["python", "app.py"]

Starten

docker build -t flaskapp .
docker run -d -p 5000:5000 flaskapp

👉 Browser öffnen: http://localhost:5000


6. Nützliche Docker-Befehle (Cheatsheet)

  • docker ps laufende Container
  • docker ps -a alle Container (inkl. gestoppter)
  • docker images vorhandene Images
  • docker stop <id> Container stoppen
  • docker rm <id> Container löschen
  • docker rmi <image> Image löschen
  • docker exec -it <id> bash in Container einsteigen

Damit hast du einen vollständigen Überblick über Docker:

  • Grundidee
  • Vorteile/Anwendungsfälle
  • Installation
  • Praxis mit Linux und Python

Anwendungsbeispiel

🐳 Docker Anwendungsbeispiel - Detaillierte Erklärung für Einsteiger

📚 Was ist Docker überhaupt?

Docker ist wie ein "Umzugskarton für Software":

  • Stell Dir vor, Du willst Deine App an einen Freund verschicken
  • Statt nur den Code zu senden, packst Du alles ein: Code, Python, alle Bibliotheken, Konfiguration
  • Dein Freund öffnet den "Karton" (Container) und alles läuft sofort - egal welches Betriebssystem er hat

📁 Projektstruktur mit Erklärungen

python-docker-project/
├── app/                          # 📂 Unser Python-Code
│   ├── __init__.py              #    (macht 'app' zu einem Python-Paket)
│   ├── main.py                  #    Hauptprogramm
│   ├── data_processor.py        #    Modul für Datenverarbeitung
│   └── database.py              #    Modul für Datenbankzugriff
├── input/                       # 📁 Hier liegen die Input-Dateien (vom Host)
│   └── sample_data.csv         #    Beispieldatei
├── output/                      # 📁 Hier kommen verarbeitete Dateien rein
├── requirements.txt             # 📝 Liste aller Python-Pakete die wir brauchen
├── Dockerfile                   # 🐳 "Bauanleitung" für unseren Container
├── docker-compose.yml          # 🎼 "Dirigent" für mehrere Container
└── .env                         # 🔐 Geheime Einstellungen (Passwörter etc.)

🐍 Python-Code (wie gewohnt)

requirements.txt - "Einkaufsliste" für Python-Pakete

# 🛒 Diese Pakete braucht unser Programm
pandas==2.1.4           # Für Excel/CSV-Verarbeitung
psycopg2-binary==2.9.9   # Um mit PostgreSQL zu sprechen
python-dotenv==1.0.0     # Um .env-Dateien zu lesen
sqlalchemy==2.0.23       # Einfache Datenbankanbindung

💡 Warum brauche ich das?

  • Ohne Docker müsstest Du auf jedem PC manuell pip install pandas etc. machen
  • Mit Docker installiert sich das automatisch im Container

app/main.py - Unser Hauptprogramm

#!/usr/bin/env python3
"""
🎯 Das macht unser Programm:
1. Schaut in /app/input nach CSV-Dateien
2. Verarbeitet sie (quadriert Werte, etc.)
3. Speichert Ergebnis in PostgreSQL-Datenbank
4. Exportiert auch als CSV in /app/output
"""
import os
import time
from pathlib import Path
from dotenv import load_dotenv

from .data_processor import DataProcessor
from .database import DatabaseManager

def main():
    print("🚀 Starte Data Processing Pipeline...")
    
    # 📁 Diese Pfade sind INSIDE dem Container!
    input_dir = Path("/app/input")    # Gemountet von Host ./input/
    output_dir = Path("/app/output")  # Gemountet von Host ./output/
    output_dir.mkdir(exist_ok=True)
    
    # 🗄️ Verbindung zur Datenbank (anderer Container!)
    db_manager = DatabaseManager()
    processor = DataProcessor(db_manager)
    
    # 📊 Alle CSV-Dateien finden und verarbeiten
    csv_files = list(input_dir.glob("*.csv"))
    
    if not csv_files:
        print("❌ Keine CSV-Dateien im Input-Verzeichnis gefunden!")
        return
    
    for csv_file in csv_files:
        print(f"📄 Verarbeite: {csv_file.name}")
        
        # 1️⃣ Daten aus CSV laden und verarbeiten
        result_data = processor.process_file(csv_file)
        
        # 2️⃣ In PostgreSQL-Container speichern
        processor.save_to_database(result_data, csv_file.stem)
        
        # 3️⃣ Als neue CSV-Datei exportieren
        output_file = output_dir / f"processed_{csv_file.name}"
        result_data.to_csv(output_file, index=False)
        print(f"💾 Gespeichert als: {output_file}")
    
    print("✅ Pipeline abgeschlossen!")

if __name__ == "__main__":
    main()

app/database.py - Spricht mit der Datenbank

import os
import pandas as pd
from sqlalchemy import create_engine, text

class DatabaseManager:
    def __init__(self):
        # 🔌 Diese Werte kommen aus der docker-compose.yml!
        self.host = os.getenv('DB_HOST', 'postgres')      # Name des DB-Containers!
        self.port = os.getenv('DB_PORT', '5432')
        self.database = os.getenv('DB_NAME', 'dataprocessing')
        self.user = os.getenv('DB_USER', 'postgres')
        self.password = os.getenv('DB_PASSWORD', 'password')
        
        # 🌐 Connection String - wie eine Adresse zur Datenbank
        self.connection_string = (
            f"postgresql://{self.user}:{self.password}@"
            f"{self.host}:{self.port}/{self.database}"
        )
        
        self.engine = None
        self._connect()
    
    def _connect(self):
        """Verbindung zur Datenbank herstellen"""
        try:
            self.engine = create_engine(self.connection_string)
            # 🏓 Kurzer Test: "Hallo Datenbank!"
            with self.engine.connect() as conn:
                conn.execute(text("SELECT 1"))
            print("✅ Datenbankverbindung erfolgreich")
        except Exception as e:
            print(f"❌ Datenbankverbindung fehlgeschlagen: {e}")
            raise
    
    def save_dataframe(self, df: pd.DataFrame, table_name: str):
        """Speichert DataFrame als Tabelle in PostgreSQL"""
        df.to_sql(
            name=table_name,
            con=self.engine,
            if_exists='replace',  # Überschreibt existierende Tabelle
            index=False
        )

(Die anderen Python-Dateien bleiben gleich)


🐳 Dockerfile - "Bauanleitung" für unseren Container

# 🏗️ SCHRITT 1: Basis-Image wählen
# Das ist wie ein "Rohbau" - Linux + Python sind schon installiert
FROM python:3.11-slim

# 🛠️ SCHRITT 2: System-Tools installieren
# Wir brauchen gcc und libpq-dev für PostgreSQL-Verbindung
RUN apt-get update && apt-get install -y \
    gcc \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*
    
# 💡 WARUM: psycopg2 (PostgreSQL-Driver) braucht diese Tools zum Kompilieren

# 📂 SCHRITT 3: Arbeitsverzeichnis setzen
WORKDIR /app
# Das ist wie "cd /app" - alle folgenden Befehle laufen hier

# 📦 SCHRITT 4: Python-Pakete installieren
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 💡 WARUM separat? Docker cached diesen Layer - muss nur neu gebaut werden wenn requirements.txt ändert

# 📋 SCHRITT 5: Unseren Code ins Container kopieren
COPY app/ ./app/
# Kopiert alles aus Host-Ordner "app/" nach Container "/app/app/"

# 📁 SCHRITT 6: Verzeichnisse erstellen
RUN mkdir -p /app/input /app/output
# Diese werden später durch Volume-Mounts "überschrieben"

# ⚙️ SCHRITT 7: Umgebungsvariablen setzen
ENV PYTHONPATH=/app                    # Python findet unsere Module
ENV PYTHONUNBUFFERED=1                 # Print-Ausgaben erscheinen sofort

# 🚀 SCHRITT 8: Was soll beim Container-Start passieren?
CMD ["python", "-m", "app.main"]
# Startet unser Hauptprogramm

🤔 Was passiert beim docker build?

  1. Docker lädt python:3.11-slim herunter (falls nicht da)
  2. Installiert gcc und PostgreSQL-Tools
  3. Kopiert requirements.txt und installiert Python-Pakete
  4. Kopiert unseren Code rein
  5. Setzt Umgebungsvariablen
  6. Ergebnis: Ein fertiger Container mit allem was wir brauchen!

docker-compose.yml - "Dirigent" für mehrere Container

# 🎯 docker-compose orchestriert MEHRERE Container gleichzeitig
version: '3.8'

services:
  # 🗄️ CONTAINER 1: PostgreSQL-Datenbank
  postgres:
    image: postgres:15                    # Fertiges PostgreSQL-Image von Docker Hub
    environment:                          # Umgebungsvariablen für PostgreSQL
      POSTGRES_DB: dataprocessing         # Name der Datenbank die erstellt wird
      POSTGRES_USER: postgres             # Benutzername
      POSTGRES_PASSWORD: password         # 🔐 Passwort (in Produktion geheimer!)
    volumes:
      - postgres_data:/var/lib/postgresql/data  # 💾 Daten persistent speichern
      - ./db_init:/docker-entrypoint-initdb.d  # 📂 Optional: SQL-Skripts beim Start
    ports:
      - "5432:5432"                       # Port freigeben (Host:Container)
    networks:
      - app_network                       # 🌐 Internes Netzwerk für Container-Kommunikation

  # 🐍 CONTAINER 2: Unsere Python-Anwendung
  python_app:
    build: .                              # 🏗️ Baue Container aus Dockerfile in diesem Verzeichnis
    environment:                          # Diese Variablen kann unser Python-Code lesen
      DB_HOST: postgres                   # ❗ WICHTIG: Name des DB-Containers (nicht localhost!)
      DB_PORT: 5432
      DB_NAME: dataprocessing
      DB_USER: postgres
      DB_PASSWORD: password
    volumes:                              # 📂 Verbinde Host-Verzeichnisse mit Container
      - ./input:/app/input:ro             # Host ./input → Container /app/input (read-only)
      - ./output:/app/output              # Host ./output → Container /app/output (read-write)
    depends_on:                           # ⏱️ Warte bis postgres-Container läuft
      - postgres
    networks:
      - app_network                       # 🌐 Gleiches Netzwerk = können miteinander sprechen
    restart: unless-stopped               # 🔄 Automatisch neu starten bei Absturz

  # 🌐 CONTAINER 3: pgAdmin (Web-Interface für PostgreSQL)
  pgadmin:
    image: dpage/pgadmin4:8
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@example.com
      PGADMIN_DEFAULT_PASSWORD: admin
    ports:
      - "8080:80"                         # 🌐 Zugriff via http://localhost:8080
    depends_on:
      - postgres
    networks:
      - app_network

# 💾 VOLUMES: Persistente Datenspeicherung
volumes:
  postgres_data:                          # Docker verwaltet diesen Speicher automatisch
  # 💡 Auch wenn Container gelöscht wird, bleiben Daten erhalten

# 🌐 NETWORKS: Virtuelle Netzwerke für Container-Kommunikation
networks:
  app_network:
    driver: bridge                        # Standard-Netzwerk-Typ
    # 💡 Alle Container in diesem Netzwerk können sich über Namen erreichen

🤔 Warum docker-compose?

  • Ohne compose: docker run postgres, dann docker run python_app - sehr umständlich!
  • Mit compose: Ein Befehl (docker-compose up) startet ALLES automatisch
  • Networks: Container können sich über Namen finden (postgres statt IP-Adresse)
  • Volumes: Daten gehen nicht verloren beim Container-Neustart

🔧 .env - Geheime Konfiguration

# 🔐 Sensible Daten sollten NICHT in docker-compose.yml stehen
# Diese Datei wird von docker-compose automatisch gelesen

# Datenbankverbindung
DB_HOST=postgres
DB_PORT=5432
DB_NAME=dataprocessing
DB_USER=postgres
DB_PASSWORD=password              # ❗ In Produktion: sicheres Passwort!

# Python-Einstellungen
PYTHONPATH=/app
PYTHONUNBUFFERED=1

💡 Wichtig: Die .env-Datei niemals in Git committen! (→ .gitignore)


📊 Beispiel-Daten

input/sample_data.csv

id,name,value,category
1,Item A,10,electronics
2,Item B,25,clothing
3,Item C,15,electronics
4,Item D,30,books
5,Item E,8,clothing

💡 Das ist eine normale CSV-Datei auf Deinem Host-PC

  • Liegt in ./input/sample_data.csv
  • Wird in den Container als /app/input/sample_data.csv "gemountet"
  • Unser Python-Code kann sie lesen, als wäre sie im Container

🚀 Schritt-für-Schritt Anleitung

1. Projekt erstellen

# Verzeichnis erstellen
mkdir python-docker-project
cd python-docker-project

# Struktur erstellen
mkdir -p app input output
touch requirements.txt Dockerfile docker-compose.yml .env
touch app/__init__.py app/main.py app/data_processor.py app/database.py

2. Code schreiben

  • Alle Dateien wie oben gezeigt erstellen und befüllen

3. Container bauen und starten

# Alle Container bauen und starten
docker-compose up --build

# 🔍 Was passiert:
# 1. Docker baut unseren Python-Container (aus Dockerfile)
# 2. Lädt PostgreSQL-Image herunter
# 3. Lädt pgAdmin-Image herunter  
# 4. Erstellt Netzwerk "app_network"
# 5. Startet postgres-Container
# 6. Startet python_app-Container (wartet auf postgres)
# 7. Startet pgAdmin-Container

4. Überprüfen ob alles läuft

# Laufende Container anzeigen
docker-compose ps

# Logs ansehen
docker-compose logs python_app
docker-compose logs postgres

# In pgAdmin einloggen: http://localhost:8080
# Email: admin@example.com, Passwort: admin

5. Neue Daten verarbeiten

# Neue CSV-Datei ins input-Verzeichnis kopieren
cp neue_daten.csv input/

# Python-App neu starten um neue Dateien zu verarbeiten
docker-compose restart python_app

# Ergebnis ansehen
ls -la output/

6. System stoppen

# Alle Container stoppen
docker-compose down

# Container stoppen UND Daten löschen (Vorsicht!)
docker-compose down -v

🔍 Docker-Befehle erklärt

Grundlegende Container-Befehle

# 📋 Alle laufenden Container anzeigen
docker ps

# 📋 Alle Container anzeigen (auch gestoppte)
docker ps -a

# 🔍 Container-Logs ansehen
docker logs <container-name>

# 🔑 In laufenden Container "einsteigen"
docker exec -it <container-name> bash

# 🗑️ Container stoppen
docker stop <container-name>

# 🗑️ Container löschen
docker rm <container-name>

Image-Befehle

# 📋 Alle Images anzeigen
docker images

# 🏗️ Image aus Dockerfile bauen
docker build -t mein-python-app .

# 🗑️ Image löschen
docker rmi <image-name>

# 🧹 Unbenutzte Images löschen
docker image prune

docker-compose-Befehle

# 🚀 Alle Services starten
docker-compose up

# 🚀 Im Hintergrund starten
docker-compose up -d

# 🏗️ Images neu bauen und starten
docker-compose up --build

# 🔄 Einzelnen Service neu starten
docker-compose restart python_app

# 📋 Status aller Services
docker-compose ps

# 🔍 Logs aller Services
docker-compose logs

# 🔍 Logs eines bestimmten Service
docker-compose logs python_app

# 📈 Live-Logs verfolgen
docker-compose logs -f python_app

# 🔑 In Container einsteigen
docker-compose exec python_app bash
docker-compose exec postgres psql -U postgres -d dataprocessing

# ⏹️ Alle Services stoppen
docker-compose down

# 🗑️ Services stoppen und Volumes löschen
docker-compose down -v

🌟 Die wichtigsten Docker-Konzepte

1. Images vs Container

  • Image = "Bauplan" (wie ein Kuchenrezept)
  • Container = "Laufende Instanz" (wie ein gebackener Kuchen)
  • Ein Image kann viele Container erstellen

2. Volumes

volumes:
  - ./input:/app/input    # Host-Verzeichnis → Container-Verzeichnis
  • Warum? Container-Dateisystem ist temporär
  • Volume = persistenter Speicher der überlebt

3. Networks

  • Container in gleichem Netzwerk können sich über Namen erreichen
  • python_app kann postgres kontaktieren (nicht IP-Adresse!)

4. Environment Variables

environment:
  DB_HOST: postgres       # Diese Variable kann Python-Code lesen

5. Ports

ports:
  - "8080:80"            # Host-Port : Container-Port
  • Container-Port 80 wird auf Host-Port 8080 freigegeben
  • Zugriff: http://localhost:8080

Häufige Anfänger-Probleme

Problem 1: "Connection refused" zur Datenbank

❌ FALSCH:  DB_HOST=localhost
✅ RICHTIG: DB_HOST=postgres
  • In Docker ist localhost der Container selbst
  • Verwende den Service-Namen aus docker-compose.yml

Problem 2: "File not found"

❌ FALSCH: input_dir = Path("./input")
✅ RICHTIG: input_dir = Path("/app/input")  
  • Pfade sind INSIDE dem Container, nicht auf dem Host

Problem 3: "Module not found"

❌ FALSCH: Umgebungsvariable vergessen
✅ RICHTIG: ENV PYTHONPATH=/app in Dockerfile

Problem 4: Änderungen nicht sichtbar

# Nach Code-Änderungen Container neu bauen:
docker-compose up --build

Problem 5: Port bereits belegt

❌ Error: Port 5432 already in use
✅ Lösung: Anderen Port verwenden: "5433:5432"

🎯 Zusammenfassung - Was macht was?

Datei/Komponente Was es macht Warum wichtig
Dockerfile "Bauanleitung" für Python-Container Definiert was IN den Container kommt
docker-compose.yml Orchestriert mehrere Container Ein Befehl startet alles
requirements.txt Liste der Python-Pakete Automatische Installation
.env Geheime Konfiguration Passwörter nicht in Code
volumes Datenaustausch Host ↔ Container Input/Output-Dateien
networks Container-Kommunikation python_app kann postgres erreichen
ports Zugriff von außen Web-Interface erreichbar

🚀 Mit einem Befehl hast Du:

  • Python-Umgebung mit allen Paketen
  • PostgreSQL-Datenbank
  • Web-Interface für DB
  • Automatische File-Verarbeitung
  • Persistente Datenspeicherung

Das ist die Macht von Docker! 🐳