Artikel

Containerisierung mit Docker und Kubernetes

Containerisierung mit Docker und Kubernetes

Die Containerisierung hat die Art und Weise revolutioniert, wie wir Software erstellen, versenden und ausführen. Durch das Packen von Anwendungen mit ihren Abhängigkeiten in leichte, tragbare Einheiten lösen Container das Problem „Es funktioniert auf meinem Computer“ und ermöglichen eine konsistente Bereitstellung in Entwicklungs-, Test- und Produktionsumgebungen.

3 Min. LesezeitSprache: DE DeutschKostenlos0 Claps0 Kommentare
TechnologieEngineering-ArtikelDevOpsDockerKubernetesTechnologyEngineering ArticlesContainerization
Leseoptionen

Einführung

Die Containerisierung hat die Art und Weise revolutioniert, wie wir Software erstellen, versenden und ausführen. Durch das Packen von Anwendungen mit ihren Abhängigkeiten in leichte, tragbare Einheiten lösen Container das Problem „Es funktioniert auf meinem Computer“ und ermöglichen eine konsistente Bereitstellung in Entwicklungs-, Test- und Produktionsumgebungen.

Docker hat Container zugänglich gemacht. Kubernetes machte sie im großen Maßstab beherrschbar. Zusammen bilden sie das Rückgrat der modernen Cloud-nativen Anwendungsbereitstellung.


Was sind Container?

Container vs. virtuelle Maschinen

┌───────────────────────┐  ┌───────────────────────┐
│    Virtual Machine     │  │      Container         │
├───────────────────────┤  ├───────────────────────┤
│  ┌─────────────────┐  │  │  ┌─────────────────┐  │
│  │   Application   │  │  │  │   Application   │  │
│  ├─────────────────┤  │  │  ├─────────────────┤  │
│  │   Guest OS      │  │  │  │   Dependencies   │  │
│  │   (full kernel) │  │  │  ├─────────────────┤  │
│  ├─────────────────┤  │  │  │   Container      │  │
│  │   Hypervisor    │  │  │  │   Runtime        │  │
│  ├─────────────────┤  │  │  ├─────────────────┤  │
│  │   Host OS       │  │  │  │   Host OS        │  │
│  └─────────────────┘  │  │  │   Kernel (shared)│  │
└───────────────────────┘  │  └─────────────────┘  │
                           └───────────────────────┘
Besonderheit VM Container
Bootzeit Minuten Millisekunden
Größe GB MB
OS-Overhead Vollständiges Betriebssystem pro VM Gemeinsamer Kernel
Isolierung Stark (Hardware-Ebene) Prozessebene
Leistung Fast einheimisch Fast einheimisch
Portabilität Gut Exzellent
Dichte Niedrig (10–100 pro Host) Hoch (100–1000 pro Host)

Docker: Die Containerplattform

Schlüsselkonzepte

Konzept Beschreibung
Bild Eine schreibgeschützte Vorlage mit Anweisungen zum Erstellen eines Containers
Container Eine ausführbare Instanz eines Bildes
Docker-Datei Eine Textdatei mit Anweisungen zum Erstellen eines Bildes
Registrierung Speicherung und Verteilung für Bilder (Docker Hub, ECR, GCR)
Volumen Permanente Datenspeicherung außerhalb des Container-Dateisystems
Netzwerk Kommunikation zwischen Containern und der Außenwelt
Komponieren Definieren Sie Multi-Container-Anwendungen und führen Sie sie aus

Best Practices für Dockerfile

# 1. Use specific base images (not 'latest')
FROM node:20-alpine AS builder

# 2. Set working directory
WORKDIR /app

# 3. Copy dependency files first (leverage layer caching)
COPY package*.json ./
RUN npm ci --production

# 4. Copy application code last
COPY . .

# 5. Use multi-stage builds
FROM node:20-alpine AS production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist

# 6. Run as non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# 7. Expose only necessary ports
EXPOSE 3000

# 8. Use exec form of CMD
CMD ["node", "dist/server.js"]

Spickzettel für Docker-Befehle

# Build image
docker build -t myapp:1.0 .

# Run container
docker run -d --name myapp -p 3000:3000 myapp:1.0

# Execute command in running container
docker exec -it myapp bash

# View logs
docker logs -f myapp

# List containers
docker ps -a

# Stop and remove
docker stop myapp && docker rm myapp

# Volumes (persistent data)
docker volume create data-volume
docker run -v data-volume:/app/data myapp:1.0

# Compose (multi-service)
docker compose up -d
docker compose logs -f
docker compose down

Docker-Netzwerk

# docker-compose.yml
version: '3.8'
services:
  web:
    image: myapp:latest
    ports:
      - "3000:3000"
    networks:
      - frontend
      - backend
    depends_on:
      - api
      - db

  api:
    image: api:latest
    networks:
      - backend
    environment:
      - DB_HOST=db

  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - backend
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

networks:
  frontend:
  backend:

volumes:
  postgres_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

Kubernetes: Container-Orchestrierung

Kubernetes (K8s) automatisiert die Bereitstellung, Skalierung und Verwaltung von Containeranwendungen in einem Cluster.

Architektur

┌──────────────────────────────────────────────┐
│            Kubernetes Control Plane          │
│  ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│  │ API      │ │ Scheduler│ │ Controller   │ │
│  │ Server   │ │          │ │ Manager      │ │
│  └──────────┘ └──────────┘ └──────────────┘ │
│  ┌─────────────────────────────────────────┐│
│  │ etcd (distributed key-value store)      ││
│  └─────────────────────────────────────────┘│
└─────────────────┬────────────────────────────┘
                  │
┌─────────────────▼────────────────────────────┐
│                Worker Nodes                   │
│  ┌──────────────────────────────────────────┐│
│  │ Node 1                                   ││
│  │  ┌──────┐ ┌──────┐ ┌──────┐             ││
│  │  │ Pod  │ │ Pod  │ │ Pod  │             ││
│  │  └──────┘ └──────┘ └──────┘             ││
│  │  ┌────────────────────────────────────┐ ││
│  │  │ kubelet ││ kube-proxy ││ container │ ││
│  │  │         ││            ││  runtime  │ ││
│  │  └────────────────────────────────────┘ ││
│  └──────────────────────────────────────────┘│
│  ┌──────────────────────────────────────────┐│
│  │ Node 2 (same structure)                  ││
│  └──────────────────────────────────────────┘│
└──────────────────────────────────────────────┘

Kernobjekte von Kubernetes

Pod – Kleinste einsetzbare Einheit

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
    - name: myapp-container
      image: nginx:1.25
      ports:
        - containerPort: 80
      resources:
        requests:
          memory: "128Mi"
          cpu: "250m"
        limits:
          memory: "256Mi"
          cpu: "500m"

Bereitstellung – Deklarative Pod-Verwaltung

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:1.0
          ports:
            - containerPort: 3000
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 3
            periodSeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1

Dienst – Stabiler Netzwerkzugriff

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
    - port: 80
      targetPort: 3000
      protocol: TCP
  type: ClusterIP  # Internal access only
---
# For external access:
apiVersion: v1
kind: Service
metadata:
  name: myapp-loadbalancer
spec:
  selector:
    app: myapp
  ports:
    - port: 80
      targetPort: 3000
  type: LoadBalancer

Eingang – HTTP/HTTPS-Routing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80

ConfigMap und Secret – Konfiguration

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  DB_HOST: postgres-service
  LOG_LEVEL: info
---
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  DB_PASSWORD: c3VwZXJzZWNyZXQ=  # base64 encoded

Bereitstellen einer Anwendung

# Apply configurations
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

# Check status
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get ingress

# View logs
kubectl logs -f deployment/myapp-deployment

# Scale
kubectl scale deployment/myapp-deployment --replicas=5

# Rollout update
kubectl set image deployment/myapp-deployment myapp=myapp:2.0
kubectl rollout status deployment/myapp-deployment

# Rollback if needed
kubectl rollout undo deployment/myapp-deployment

Erweiterte Funktionen von Kubernetes

Horizontaler Pod-Autoscaler (HPA)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp-deployment
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

Persistente Volumes

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard
---
apiVersion: v1
kind: Pod
metadata:
  name: postgres
spec:
  containers:
    - name: postgres
      image: postgres:16-alpine
      volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: postgres-storage
  volumes:
    - name: postgres-storage
      persistentVolumeClaim:
        claimName: data-claim

Namensräume

# Create namespaces for environment isolation
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production

# Deploy to specific namespace
kubectl apply -f deployment.yaml -n production

# Resource quotas per namespace
kubectl create quota prod-quota --hard=cpu=40,memory=80Gi,pods=50 -n production

Docker vs. Kubernetes – Wann was zu verwenden

Szenario Docker allein Kubernetes hinzufügen
Lokale Entwicklung ✅ Ja ❌ Übertrieben
Bereitstellung auf einem einzelnen Server ✅ Ja ❌ Übertrieben
2-3 Mikrodienste ✅ Docker Compose ❌ Normalerweise übertrieben
Hohe Verfügbarkeit erforderlich ❌ Manuelles Failover ✅ Automatische Heilung
Automatische Skalierung erforderlich ❌ Handbuch ✅ HPA
Cluster mit mehreren Knoten ❌ Begrenzt ✅ Eingebaut
Fortlaufende Updates ❌ Handbuch ✅ Eingebaut
Canary-Bereitstellungen ❌ Komplex ✅ Native Unterstützung
Multi-Cloud ❌ Nicht tragbar ✅ Tragbar

Entscheidungsrahmen:

  1. Beginnen Sie mit Docker – Immer. Container sind das Fundament.
  2. Verwenden Sie Docker Compose – Für lokale Entwicklungs-, CI- und Einzelhostbereitstellungen.
  3. Nehmen Sie Kubernetes ein, wenn: Sie HA, Skalierung, mehrere Knoten oder komplexe Orchestrierung benötigen.
  4. Verwenden Sie verwaltetes Kubernetes (EKS, AKS, GKE) – Vermeiden Sie die Selbstverwaltung der Steuerungsebene.

Best Practices

Imagebildung

  • Verwenden Sie spezifische Basis-Image-Tags („node:20-alpine“, nicht „node:latest“).
  • Implementieren Sie mehrstufige Builds, um die Bildgröße zu minimieren.
  • Bilder auf Schwachstellen scannen: „docker scan myapp:1.0“.
  • Bilder signieren: „cosign sign --key cosign.key myapp:1.0“.

Sicherheit

  • Führen Sie Container als Nicht-Root-Benutzer aus.
  • Legen Sie schreibgeschütztes Root-Dateisystem fest: „readOnlyRootFilesystem: true“.
  • Verwenden Sie Geheimnisse für vertrauliche Daten, nicht für Umgebungsvariablen.
  • Implementieren Sie Netzwerkrichtlinien, um den Datenverkehr zwischen Pods einzuschränken.
  • Aktivieren Sie RBAC für den Kubernetes-API-Zugriff.

Ressourcenmanagement

  • Legen Sie immer Ressourcenanforderungen und -limits fest.
  • Verwenden Sie Ressourcenkontingente pro Namespace.
  • Implementieren Sie HPA für die automatische Skalierung.
  • Verwenden Sie PodDisruptionBudget für die Verfügbarkeit während der Wartung.

Überwachung und Beobachtbarkeit

# Sidecar pattern for logging
spec:
  containers:
    - name: app
      image: myapp:latest
    - name: log-collector
      image: fluentd:latest
      volumeMounts:
        - name: logs
          mountPath: /var/log/app

CI/CD-Pipeline

# GitHub Actions — Build + Deploy to Kubernetes
name: CI/CD
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image
        run: docker build -t registry.example.com/myapp:${{ github.sha }} .
      - name: Push to registry
        run: docker push registry.example.com/myapp:${{ github.sha }}
      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/myapp-deployment \
            myapp=registry.example.com/myapp:${{ github.sha }}

Das Ökosystem

Kategorie Werkzeuge
Containerlaufzeit Docker, Containerd, CRI-O
Orchestrierung Kubernetes, Nomad, Docker Swarm
Paketmanager Helm, Kustomize
Service Mesh Istio, Linkerd, Cilium
Überwachung Prometheus + Grafana, Datadog
Protokollierung ELK Stack, Grafana Loki, fließend
Sicherheit Trivy, Falco, OPA/Gatekeeper, Kyverno
GitOps ArgoCD, Flux
Entwicklertools Skaffold, Tilt, DevSpace
Lagerung Rook/Ceph, Longhorn, Portworx
Serverlos auf K8s Knative, OpenFaaS, KEDA

Abschluss

Docker und Kubernetes bieten zusammen eine leistungsstarke Plattform zum Erstellen, Bereitstellen und Skalieren moderner Anwendungen:

  1. Beginnen Sie mit Docker – Containerisieren Sie Anwendungen, Master-Docker-Dateien und Compose.
  2. Erlernen Sie die Grundlagen von Kubernetes – Pods, Bereitstellungen, Dienste, ConfigMaps.
  3. Verwenden Sie verwaltetes Kubernetes – Lassen Sie Cloud-Anbieter die Steuerungsebene übernehmen.
  4. GitOps übernehmen – ArgoCD oder Flux für deklarative, versionierte Bereitstellungen.
  5. In Beobachtbarkeit investieren – Überwachung, Protokollierung und Rückverfolgung sind im großen Maßstab unerlässlich.

Die Investition in das Erlernen der Containerisierung und Orchestrierung zahlt sich in der Bereitstellungszuverlässigkeit, der betrieblichen Effizienz und der Anwendungsportabilität über Umgebungen hinweg aus.

Empfohlene Artikel

6 Coding-Patterns, die ich von Senior Engineers gelernt habe
EditorialDE
8 Min.Kostenlos

6 Coding-Patterns, die ich von Senior Engineers gelernt habe

TechnologieCodeCoding
0 Claps
Lesen
Einen privaten KI-Assistenten für Notizen bauen
EmpfohlenDE
9 Min.Kostenlos

Einen privaten KI-Assistenten für Notizen bauen

Mache aus Markdown-Notizen einen durchsuchbaren Assistenten, ohne private Entwürfe offenzulegen.

TechnologiePlattform-LeitfädenKI-SchreibenAIAutomationData
0 Claps
Lesen
Rechnungsdaten mit OCR automatisiert auslesen
EditorialDE
8 Min.Kostenlos

Rechnungsdaten mit OCR automatisiert auslesen

Baue eine Pipeline, die Rechnungen liest, Felder extrahiert und unsichere Werte markiert.

TechnologieEngineering-ArtikelKI-SchreibenAIAutomationData
0 Claps
Lesen

Kommentare

0 Kommentare

Noch keine freigegebenen Kommentare sichtbar. Neue Antworten können moderiert werden.