Zum Hauptinhalt springen

🐳 Was ist Docker?

πŸ“– Definition​

Docker ist eine Plattform, die Anwendungen in isolierten Umgebungen namens Container ausfΓΌhrt. Container bΓΌndeln eine Anwendung mit allen benΓΆtigten AbhΓ€ngigkeiten, sodass sie ΓΌberall identisch ausgefΓΌhrt werden kΓΆnnen. Es lΓΆst das "Auf meinem Rechner funktioniert es..."-Problem und macht Entwicklung, Tests und Deployment einfach und konsistent.

🎯 Verstehen durch Analogien​

Versandcontainer​

Docker kann man mit Frachtcontainern vergleichen:

Traditioneller Versand (VM)
β”œβ”€ Unterschiedliche Verpackung pro Artikel
β”œβ”€ Verschiedene Grâßen/Gewichte
β”œβ”€ Unterschiedliche Transportmethoden
└─ Ineffizient, komplex

Container-Versand (Docker)
β”œβ”€ Standardisierte Container
β”œβ”€ Kann beliebige Artikel aufnehmen
β”œβ”€ Schiff, LKW, Bahn - ΓΌberall gleich transportierbar
└─ Effizient, einfach

Docker Container = Standardisiertes Softwarepaket

Wohnung vs. Einfamilienhaus​

Virtual Machine (VM) = Einfamilienhaus
β”œβ”€ Jedes Haus braucht komplette Infrastruktur
β”œβ”€ GrundstΓΌck, GebΓ€ude, Strom, Wasser alles separat
β”œβ”€ Hohe Kosten
└─ Langsamer Start

Docker Container = Wohnung
β”œβ”€ Gemeinsame Infrastruktur (GrundstΓΌck, GebΓ€ude)
β”œβ”€ Jede Wohnung unabhΓ€ngig
β”œβ”€ Effizient
└─ Schneller Einzug

βš™οΈ Funktionsweise​

1. Docker-Architektur​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Docker Client (CLI) β”‚
β”‚ docker run, docker build, usw. β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ API-Aufrufe
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Docker Daemon β”‚
β”‚ Container-/Image-Verwaltung β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Container (laufende Apps) β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚App 1β”‚ β”‚App 2β”‚ β”‚App 3β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Host OS (Linux Kernel) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Image vs Container​

Image = Bauplan, Klasse
β”œβ”€ Nur lesbar
β”œβ”€ Aus Schichten aufgebaut
β”œβ”€ Wiederverwendbar
└─ Beispiel: ubuntu, node, nginx

Container = Laufende Instanz, Objekt
β”œβ”€ Aus Image erstellt
β”œβ”€ AusfΓΌhrbar
β”œβ”€ Isolierte Umgebung
└─ Mehrere Instanzen mΓΆglich

Beziehung:
Image β†’ Container 1
β†’ Container 2
β†’ Container 3

3. Dockerfile β†’ Image β†’ Container​

1. Dockerfile schreiben (Rezept)
β”œβ”€ FROM node:18
β”œβ”€ COPY package.json .
β”œβ”€ RUN npm install
└─ CMD ["npm", "start"]

2. Image bauen (Kochen)
docker build -t my-app .

3. Container ausfΓΌhren (Servieren)
docker run -p 3000:3000 my-app

πŸ’‘ Praxisbeispiele​

Dockerfile schreiben​

# Node.js Anwendung Dockerfile

# Basis-Image
FROM node:18-alpine

# Arbeitsverzeichnis festlegen
WORKDIR /app

# package.json kopieren
COPY package*.json ./

# AbhΓ€ngigkeiten installieren
RUN npm ci --only=production

# Quellcode kopieren
COPY . .

# Port freigeben
EXPOSE 3000

# Umgebungsvariable
ENV NODE_ENV=production

# Befehl beim Container-Start
CMD ["node", "server.js"]

Image bauen und ausfΓΌhren​

# 1. Image bauen
docker build -t my-node-app:1.0 .
# -t: Tag (Name:Version)
# .: Dockerfile im aktuellen Verzeichnis

# 2. Image prΓΌfen
docker images
# REPOSITORY TAG IMAGE ID CREATED
# my-node-app 1.0 abc123 2 minutes ago

# 3. Container ausfΓΌhren
docker run -d \
--name my-app \
-p 3000:3000 \
-e NODE_ENV=production \
my-node-app:1.0

# -d: Hintergrund-AusfΓΌhrung
# --name: Container-Name
# -p: Port-Mapping (Host:Container)
# -e: Umgebungsvariable

# 4. Laufende Container prΓΌfen
docker ps

# 5. Logs anzeigen
docker logs my-app

# 6. In Container zugreifen
docker exec -it my-app sh

# 7. Container stoppen
docker stop my-app

# 8. Container lΓΆschen
docker rm my-app

# 9. Image lΓΆschen
docker rmi my-node-app:1.0

Docker Compose (Mehrere Container verwalten)​

# docker-compose.yml

version: '3.8'

services:
# Webanwendung
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=database
depends_on:
- database
- redis
volumes:
- ./logs:/app/logs

# Datenbank
database:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=myapp
volumes:
- db-data:/var/lib/mysql
ports:
- "3306:3306"

# Cache
redis:
image: redis:7-alpine
ports:
- "6379:6379"

# Nginx (Reverse Proxy)
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web

volumes:
db-data:
# Docker Compose Befehle

# Alle Services starten
docker-compose up -d

# Logs anzeigen
docker-compose logs -f web

# Bestimmten Service neu starten
docker-compose restart web

# Services skalieren
docker-compose up -d --scale web=3

# Alle Services stoppen und lΓΆschen
docker-compose down

# Mit Volumes lΓΆschen
docker-compose down -v

Praxisbeispiel: React + Node.js + MongoDB​

# frontend/Dockerfile
FROM node:18-alpine AS build

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Statische Dateien mit Nginx bereitstellen
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# backend/Dockerfile
FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

EXPOSE 5000
CMD ["node", "server.js"]
# docker-compose.yml
version: '3.8'

services:
frontend:
build:
context: ./frontend
ports:
- "80:80"
depends_on:
- backend

backend:
build:
context: ./backend
ports:
- "5000:5000"
environment:
- MONGO_URL=mongodb://mongodb:27017/myapp
depends_on:
- mongodb

mongodb:
image: mongo:6
volumes:
- mongo-data:/data/db
ports:
- "27017:27017"

volumes:
mongo-data:

Daten-Volume-Verwaltung​

# Volume erstellen
docker volume create my-data

# Volume-Liste
docker volume ls

# Volume an Container mounten
docker run -v my-data:/app/data my-app

# Host-Verzeichnis mounten (nΓΌtzlich bei Entwicklung)
docker run -v $(pwd):/app my-app

# Read-only Mount
docker run -v $(pwd):/app:ro my-app

# Volume lΓΆschen
docker volume rm my-data

# Alle ungenutzten Volumes lΓΆschen
docker volume prune

.dockerignore Datei​

# .dockerignore

# Git
.git
.gitignore

# Node
node_modules
npm-debug.log

# Umgebungskonfiguration
.env
.env.local

# Build-Artefakte
dist
build

# IDE
.vscode
.idea

# Tests
coverage
*.test.js

# Dokumentation
README.md
docs/

πŸ€” HΓ€ufig gestellte Fragen​

F1. Docker vs Virtual Machine?​

A:

Virtual Machine (VM)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ App A β”‚ β”‚ App B β”‚
β”‚ Libs β”‚ β”‚ Libs β”‚
β”‚ Guest OS β”‚ β”‚ Guest OS β”‚
β”‚ (Linux) β”‚ β”‚ (Ubuntu) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Hypervisor (VMware etc.) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Host OS β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Docker Container
β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”
β”‚ App A β”‚ β”‚ App B β”‚ β”‚ App C β”‚
β”‚ Libs β”‚ β”‚ Libs β”‚ β”‚ Libs β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Docker Engine β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Host OS (Linux Kernel) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Vergleich:
VM Docker
Grâße GB MB
Start Minuten Sekunden
Isolation Komplett Prozess-Ebene
Leistung Hoher Overhead Fast nativ
PortabilitΓ€t Niedrig Hoch

F2. Was sind Docker Image-Schichten?​

A:

FROM node:18          # Schicht 1: Basis-Image
WORKDIR /app # Schicht 2: Arbeitsverzeichnis
COPY package.json . # Schicht 3: package.json
RUN npm install # Schicht 4: AbhΓ€ngigkeiten installieren
COPY . . # Schicht 5: Quellcode
CMD ["node", "app.js"]# Schicht 6: Startbefehl

# Schichten-Caching
# - UnverΓ€nderte Schichten werden wiederverwendet
# - Beschleunigt Build-Prozess

# βœ… Gutes Beispiel: HΓ€ufig geΓ€nderte Dinge spΓ€ter
COPY package.json .
RUN npm install # Gecacht (wenn package.json unverΓ€ndert)
COPY . . # Nur Code geΓ€ndert

# ❌ Schlechtes Beispiel: HÀufig geÀnderte Dinge zuerst
COPY . . # Bei Code-Γ„nderung
RUN npm install # npm install erneut ausfΓΌhren!

F3. Was ist Container-Orchestrierung?​

A:

Einzelner Server
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”Œβ”€β”€β”€β” β”Œβ”€β”€β”€β” β”Œβ”€β”€β”€β” β”‚
β”‚ β”‚C1 β”‚ β”‚C2 β”‚ β”‚C3 β”‚ β”‚
β”‚ β””β”€β”€β”€β”˜ β””β”€β”€β”€β”˜ β””β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Orchestrierung (Kubernetes)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Server1 β”‚ β”‚ Server2 β”‚ β”‚ Server3 β”‚
β”‚ β”Œβ”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β” β”‚
β”‚ β”‚C1 β”‚ β”‚ β”‚ β”‚C2 β”‚ β”‚ β”‚ β”‚C3 β”‚ β”‚
β”‚ β””β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Funktionen:
- Automatisches Deployment
- Skalierung (automatische Vergrâßerung/Verkleinerung)
- Load Balancing
- Automatische Wiederherstellung (Container neu starten wenn tot)
- Rolling Updates

Tools:
- Kubernetes (am beliebtesten)
- Docker Swarm
- Amazon ECS

F4. Wie nutzt man Docker in der Entwicklungsumgebung?​

A:

# Szenario: Jedes Teammitglied hat unterschiedliche Umgebung

# Teammitglied A: macOS, Node 16
# Teammitglied B: Windows, Node 18
# Teammitglied C: Linux, Node 14

# Problem: "Auf meinem Rechner funktioniert es..."

# LΓΆsung: Umgebung mit Docker vereinheitlichen

# docker-compose.yml
version: '3.8'
services:
app:
image: node:18
volumes:
- .:/app
working_dir: /app
command: npm run dev
ports:
- "3000:3000"

# Alle Teammitglieder haben identische Umgebung
docker-compose up

# Vorteile:
# 1. Node.js-Installation nicht erforderlich
# 2. Version vereinheitlicht
# 3. AbhΓ€ngigkeiten isoliert
# 4. Umgebungskonfiguration geteilt

F5. Wie sicher ist Docker?​

A:

# βœ… Sicherheits-Best Practices

# 1. Minimales Basis-Image
FROM node:18-alpine # βœ… Klein und sicher
FROM node:18 # ❌ Viele unnâtige Tools

# 2. Als Nicht-Root-Benutzer ausfΓΌhren
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs # βœ… Minimale Berechtigungen

# 3. Sensible Informationen ausschließen
# In .dockerignore hinzufΓΌgen
.env
*.key
secrets/

# 4. Multi-Stage Build (unnΓΆtige Tools entfernen)
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build

FROM node:18-alpine # Kleines Image
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]

# 5. Image scannen
docker scan my-image

# 6. Read-only Root-Dateisystem
docker run --read-only my-app

# 7. Ressourcen-Limits
docker run --memory="512m" --cpus="1" my-app

πŸŽ“ NΓ€chste Schritte​

Wenn Sie Docker verstanden haben, lernen Sie als nΓ€chstes:

  1. Was ist Git? (noch zu schreiben) - Versionskontrolle und Deployment
  2. Was ist Node.js? (noch zu schreiben) - Node-Apps mit Docker deployen
  3. Was ist TDD? - Tests in Docker ausfΓΌhren

Ausprobieren​

# 1. Docker-Installation prΓΌfen
docker --version

# 2. Hello World
docker run hello-world

# 3. Nginx ausfΓΌhren
docker run -d -p 8080:80 nginx
# http://localhost:8080 aufrufen

# 4. Container prΓΌfen
docker ps

# 5. Stoppen und lΓΆschen
docker stop <container-id>
docker rm <container-id>

# 6. Eigene App containerisieren
# - Dockerfile schreiben
# - docker build
# - docker run

NΓΌtzliche Befehle​

# Image-Verwaltung
docker pull nginx # Image herunterladen
docker images # Image-Liste
docker rmi nginx # Image lΓΆschen

# Container-Verwaltung
docker run # Container ausfΓΌhren
docker ps # Laufende Container
docker ps -a # Alle Container
docker stop <id> # Container stoppen
docker start <id> # Container starten
docker restart <id> # Container neu starten
docker rm <id> # Container lΓΆschen

# Logs und Debugging
docker logs <id> # Logs anzeigen
docker logs -f <id> # Echtzeit-Logs
docker exec -it <id> sh # In Container zugreifen
docker inspect <id> # Detaillierte Informationen

# AufrΓ€umen
docker system prune # Ungenutzte Ressourcen lΓΆschen
docker system prune -a # Alle ungenutzten Ressourcen
docker volume prune # Ungenutzte Volumes lΓΆschen

🎬 Zusammenfassung​

Docker ist ein unverzichtbares Tool moderner Entwicklung:

  • Container: Isolierte AusfΓΌhrungsumgebung
  • Image: Anwendungspaket
  • PortabilitΓ€t: LΓ€uft ΓΌberall identisch
  • Effizienz: Leichtgewichtig und schnell

Lâsen Sie das "Auf meinem Rechner funktioniert es..."-Problem mit Docker! 🐳✨