Docker / Kubernetes / Podman verstehen

Zuletzt aktualisiert am 28. März 2026 von Lars

Wenn du in der IT unterwegs bist, wirst du immer mal wieder von Docker, Kubernetes und Podman hören. Mehr dazu findest du in diesm Artikel

Problemstellung Anwendungsbereitstellung

Betrachten wir zunächst, worum es bei Docker geht: Docker hilft bei der Bereitstellung von Anwendungen. Wenn du eine Anwendung bereitstellen möchtest, musst du nicht nur das Programm, sondern auch viele Abhängigkeiten wie Bibliotheken, Betriebssystem-Spezifikationen und externe Dienste berücksichtigen. Man denke hier zum Beispiel an die DLL-Dateien, die ein Windows-Programm in der Regel benötigt.

Früher gab es dafür zwei Hauptlösungen: klassische Installer oder virtuelle Maschinen. Beide hatten ihre Vor- und Nachteile.

Klassischer Installer

Vorteil des Installers ist seine Kompaktheit und die einfache Ausführbarkeit auf jedem Zielsystem. Problematisch wird es aber, wenn auf dem Zielsystem spezielle Konfigurationen vorhanden sein müssen, wie zum Beispiel eine bestimmte Datenbankversion, damit die Applikation einwandfrei funktioniert.

Virtuelle Maschine

Nachteil von virtuellen Maschinen ist deren Grösse. Sie enthalten immer das komplette Betriebssystem. Bei lizenzpflichtigen Betriebssystemen wird zudem immer eine eigene Lizenz benötigt. Dafür sind virtuelle Maschinen in der Regel recht universell einsetzbar.

Siehe auch: Was ist Virtualisierung?

Lösung mit Docker

Docker nutzt das Konzept von sogenannten Containern. Statt eine komplette virtuelle Maschine für jede Anwendung zu starten, isoliert Docker einfach den Prozess der Anwendung. Das bedeutet, dass mehrere Docker-Container den gleichen Betriebssystemkern nutzen können, wodurch sie leichter und schneller sind.

Docker (Container) Schemabild
Container: Jeder Container greift auf den gleichen Linux-Kernel zu.

Der Nachteil der Nutzung des Betriebssystemkerns ist aber, dass auf einem Linux nur eine Linux-Applikation laufen kann und nicht etwa eine Windows-Applikation, wie das mit Virtualisierung möglich wäre.

Klassische Virtualisierung im Gegensatz zu Docker: Auf der Hardware läuft der sogenannte Hypervisor. Auf diesem laufen dann komplette Betriebssysteme (Guest OS) virtuell voneinander getrennt.

Wie funktioniert das?

Die Idee hinter der "Containerisierung" ist, einen Prozess und all seine Abhängigkeiten in einem "Image" zu verpacken. Wenn dieses Image (oder Archiv) gestartet wird, packt Docker es in einen Container und führt es aus. Dies ist der Vorgang der "Containerisierung".

Das ist aber stark vereinfacht ausgedrückt. Ein Container kann aus mehreren sogenannten Layern bestehen, die quasi übereinandergelegt werden können. Dadurch wird RAM gespart.

Beim Neustart eines Containers werden alle bestehenden Daten verworfen und es wird quasi wieder bei Null gestartet.

Wenn konstante Daten benötigt werden, werden sogenannte Volumes eingebunden. Volumes können in mehreren Containern eingebunden (gemountet) werden.

Docker wurde entwickelt, um die Verwendung von Linux Containern für Entwickler zu vereinfachen. Es ist im Wesentlichen ein Kommandozeilen-Tool und ein Betriebssystem-Service (=Daemon), der den Prozess steuert.

Docker auf Nicht-Linux Systemen

Wenn du ein MacOS- oder Windows-Benutzer bist, benötigst du eine virtuelle Maschine, um Docker auszuführen. Mit Produkten wie "Docker for Mac" oder "Docker for Windows" ist dies nahtlos möglich und erfordert minimalen Overhead.

Vor- und Nachteile von Docker

Vorteile von Docker

Die Liste der Vor- und Nachteile von Docker ist nicht abschliessend. Sie listet nur einige wichtige Punkte für Einsteiger auf.

  • Docker-Container sind leichtgewichtig und schnell.
  • Sie bieten eine bessere Isolation als klassische Installer.
  • Sie sind ressourceneffizient und so können viele Container auf einem System ausführen.

Nachteile von Docker

  • Da alle Container denselben Kernel verwenden, kann ein Kernel-Exploit in einem Container potenziell das gesamte Host-System beeinflussen.
  • Isolierung: Die Isolierung zwischen Containern ist nicht so stark wie die von echten virtuellen Maschinen.
  • Das Arbeiten mit Anwendungen, die Daten speichern müssen (z.B. Datenbanken) kann komplizierter sein.

Was ist Podman?

Podman ist wie Docker eine Container-Engine – also ein Tool, mit dem man Anwendungen in isolierten Umgebungen (Containern) betreiben kann. Wer Docker kennt, sollte sich relativ schnell zurechtfinden: Die Befehle sind praktisch identisch.

Docker vs. Podman

Der grösste Unterschied zu Docker ist, dass Podman keinen Hintergrunddienst benötigt, der ständig läuft. Container werden einfach direkt gestartet. Ausserdem läuft Podman standardmässig ohne Administratorrechte, was es sicherer macht und den Einsatz auch auf Managed Servern ermöglicht, auf denen man in der Regel keine Root-Rechte hat.

Was ist Kubernetes?

Auch wieder stark vereinfacht – Kubernetes ist...

  • Ein System zur Verwaltung eines Clusters (Verbunds) von Docker-Containern.
  • Bietet automatisierte Planung und Verwaltung von Containern (beispielsweise Verschieben zwischen mehreren Servern).

Docker vs. Podman - praktisches Beispiel

Docker vs. Podman. Ich möchte schon länger Docker und sein Pendant besser verstehen lernen. Da ich mich mit reiner Theorie immer eher schwer tue, habe ich nach einem praktischen Beispiel gesucht.

Dies habe ich in Grafana gefunden. Ein Raspberry Pi Zero misst bei mir auf dem Balkon die Temperatur und schreibt diese in eine MySQL-Datenbank, die dann mit Grafana visualisiert werden soll.

Der folgende Abschnitt dieses Artikels dient primär als Notiz meiner Experimente und nicht als fertiges Tutorial. Vielleicht kann er dem ein oder anderen aber trotzdem helfen.

Installation und erster Test

$ sudo apt update

Benötigte Pakete für Repos einrichten

$ sudo apt install -y ca-certificates curl gnupg lsb-release

Docker GPG Key

$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Docker Repository zur APT-Quelle hinzufügen (Debian 12, da Trixie inkompatibel)

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

Docker-Engine und zugehörige Komponenten installieren

$ sudo apt install -y docker-ce docker-ce-cli containerd.io

Docker-Dienst aktivieren und sofort starten

$ sudo systemctl enable --now docker

Prüfen, ob Docker läuft

$ sudo systemctl status docker

Aktuellen Nutzer zur Gruppe Docker hinzufügen

$ sudo usermod -aG docker $USER

Änderungen wirksam machen

$ newgrp docker</docker>

Test-Container Hello World ausführen
<code>docker run --rm hello-world

Test-Container Hello World ausführen

$ docker run --rm hello-world

Docker Compose Plugin

Docker Compose ist ein Werkzeug, mit dem du mehrere Docker‑Container und deren Vernetzung in einer einzigen Textdatei („docker‑compose.yml“) beschreiben kannst. Mit einem einzigen Befehl (docker compose up) startest, stoppst oder aktualisierst du dann alle definierten Services gleichzeitig. Es vereinfacht das Management von Multi‑Container‑Setups, ohne dass du jedes "docker run "einzeln eingeben musst.

Docker Compose Version holen

$ DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep tag_name | cut -d '"' -f4)

Binary herunterladen und nach /usr/local/lib/docker/cli-plugins legen

$ sudo mkdir -p /usr/local/lib/docker/cli-plugins
$ sudo curl -SL "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-$(dpkg --print-architecture)" \
-o /usr/local/lib/docker/cli-plugins/docker-compose

Ausführungsrechte setzen

$ sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose

Prüfung

$ docker compose version

Grafana mit Docker

Unterordner - z.B. grafana - anlegen

Darin eine docker-compose.yml anlegen

 services:
 
  grafana:
    image: grafana/grafana:12.3-ubuntu
    container_name: grafana
    depends_on:
      - influxdb
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=passwordvongrafana

volumes:
  grafana_data:

Das Passwort hier im Klartext abzulegen, ist nicht Best Practice, aber wir widmen uns dem später noch.

Docker Anwendung starten

$ docker compose up

Docker-Anwendung stoppen

$ docker compose down

Laufende Anwendungen anzeigen

$ docker ps

Grafana

Die Konfiguration von Grafana werde ich in eine separate Anleitung auslagern.

Der Aufruf von Grafana erfolgt über

http://IP:3000

Temperatur-Dashboard Grafana - Legende noch nicht korrekt konfiguriert

Podman

Podman installieren

& sudo apt update && sudo apt install podman
& sudo apt install python3-pip

podman-compose installieren

sudo apt  install podman-compose

docker compose Einstellungen sichern

mv ~/.docker/cli-plugins/docker-compose ~/.docker/cli-plugins/docker-compose.bak

Dienste starten

systemctl --user enable --now podman.socket
systemctl --user status podman.socket

Container starten und überprüfen

podman compose up
podman ps

Problem Daten aus Docker-Volume

An dieser Stelle wurden die Daten nicht gefunden und das installierte Grafana-Dashboard ist verschwunden.

Container sind von Natur aus flüchtig – wird ein Container gelöscht, sind alle Daten weg. Damit das nicht passiert, kann man Daten ausserhalb des Containers speichern. Dafür gibt es zwei Varianten:

Named Volume

Docker oder Podman erstellt einen eigenen Speicherbereich und verwaltet ihn selbst. Man weiss nicht genau, wo die Daten liegen – das übernimmt das Tool.

volumes:
  - grafana_data:/var/lib/grafana

Bind Mount

Man gibt einen konkreten Ordner auf dem eigenen Computer an. Die Daten liegen genau dort, wo angegeben. Man kann jederzeit "reinschauen".

volumes:
  - ./grafana_data:/var/lib/grafana

Der . steht für "aktueller Ordner" – die Daten landen also direkt neben der compose.yml.

Das Problem beim Wechsel von Docker zu Podman

Docker und Podman verwalten ihre Named Volumes getrennt – jedes Tool hat seinen eigenen Speicherort. Erstellt man in Docker ein Volume namens grafana_data, weiss Podman nichts davon. Es erstellt einfach ein neues, leeres Volume mit demselben Namen.

Mit einem Bind Mount hat man dieses Problem nicht: Beide Tools greifen auf denselben Ordner zu – die Daten sind immer da.

Für Einsteiger sind daher Bind Mounts die bessere Wahl.

Da ich hier falsch angefangen habe, muss ich die Daten migrieren.

Schauen, wo Docker die Daten hat.

$ docker volume ls | grep grafana
$ sudo cp -r $(docker volume inspect grafana_grafana_data --format '{{.Mountpoint}}') ./grafana_data
$ sudo chown -R 472:472 ./grafana_data

In der docker-compose.yml anpassen

    volumes:
      - ./grafana_data:/var/lib/grafana   # geändert

Test

$ podman compose up

Das hat erst einmal überhaupt nicht funktioniert. Hier war dann eine längere Troubleshooting-Session mit der Claude-KI.

Docker läuft im Hintergrund als Administrator (root). Egal welcher User einen Container startet – Docker hat immer vollen Zugriff auf alle Dateien. Das ist praktisch, aber nicht besonders sicher. Podman macht das anders: Es läuft ohne Administrator-Rechte, direkt als dein normaler Benutzer. Das ist sicherer, bedeutet aber: Wenn ein Container auf einen Ordner auf deinem Computer zugreift, muss genau geprüft werden, wer auf was zugreifen darf.

User-Mapping

Innerhalb eines Containers laufen Prozesse unter eigenen User-IDs – Grafana z.B. als User 472. Aber dieser User 472 existiert auf deinem Linux-System gar nicht. Podman löst das mit einem Trick: Es übersetzt (mapped) die User-IDs im Container auf echte IDs auf deinem System. Dein Benutzer lars bekommt dafür einen reservierten Bereich zugeteilt – die sogenannten Sub-UIDs:

lars:100000:65536

Das bedeutet: Podman darf für lars die UIDs 100000 bis 165535 verwenden. User 472 im Container wird also auf uid 100471 auf dem Host gemappt (100000 + 472 - 1 = 100471).

Gehört ein Ordner auf dem Host einer anderen UID, bekommt Grafana im Container einen permission denied Fehler.

Troubleshooting Schritt für Schritt

Container läuft, aber Grafana-Fehler "readonly database"

Prüfen ob das Verzeichnis überhaupt gemountet wurde:

$ podman inspect grafana | grep -A 5 Mounts
          "Mounts": [
               {
                    "Type": "bind",
                    "Source": "/home/lars/grafana/grafana_data",
                    "Destination": "/var/lib/grafana",
                    "Driver": "",

Welchen User nutzt der Prozess im Container?

$ podman exec grafana id
uid=472(grafana) gid=0(root) groups=0(root)

Wie sieht Podman die Dateien auf dem Host?

$ podman unshare ls -la /home/lars/grafana/grafana_data/

Zeigte nobody das User-Mapping stimmt nicht, die Dateien gehören der falschen UID.

Sub-UIDs prüfen

$ cat /etc/subuid
lars:100000:65536

Korrekte UID berechnen und Berechtigungen setzen

Formel: Startuid + Container-UID - 1
Beispiel Grafana: 100000 + 472 - 1 = 100471

sudo chown -R 100471:100471 ./grafana_data

Pods automatisch starten

Bei Docker gibt es einen Hintergrunddienst (Daemon), der immer läuft und Container automatisch starten kann. Podman hat keinen solchen Dienst.

Stattdessen nutzt Podman das Init-System von Linux: systemd. Systemd ist auf fast jedem modernen Linux dafür zuständig, Dienste beim Systemstart zu starten – z.B. dedenetzwerkdienst, dedenruckerdienst usw.

Der Start wird per Quadlet definiert. Ein Quadlet ist einfach eine Konfigurationsdatei, die systemd sagt: "Starte diesen Container wie einen normalen Dienst."

Hier im konkreten faFallrstellt man eine Datei grafana.container in einem bestimmten Ordner. Podman generiert daraus automatisch eine systemd-Unit – du musst dich um nichts weiter kümmern.

Ordner für rootless (als normaler User):

~/.config/containers/systemd/

Datei erstellen

$ mkdir -p ~/.config/containers/systemd/
$ vim ~/.config/containers/systemd/grafana.container

Inhalt

[Unit]
Description=Grafana

[Container]
Image=grafana/grafana:12.3-ubuntu
PublishPort=3000:3000
Volume=/home/lars/grafana/grafana_data:/var/lib/grafana
Environment=GF_SECURITY_ADMIN_USER=admin
Environment=GF_SECURITY_ADMIN_PASSWORD=passwordvongrafana

[Service]
Restart=always

[Install]
WantedBy=default.target

Initialisieren und starten

$ systemctl --user daemon-reload
$ systemctl --user enable grafana.service
$ systemctl --user start grafana.service

Damit das auch beim Hochfahren und nicht erst beim Login des Users passiert, noch

$ sudo loginctl enable-linger lars

Normalerweise startet systemd die User-Dienste des Users "lars" erst, wenn lars sich einloggt – und stoppt sie wieder, wenn lars sich ausloggt. Das macht Sinn für Desktop-Anwendungen, aber nicht für einen Server der immer laufen soll.

enable-linger sagt systemd: „Starte die Dienste von lars bereits beim Systemstart – und lass sie laufen, auch wenn niemand eingeloggt ist."

Passwörter sicher ablegen

Passwörter in der docker-compose.yml sind nicht gut.

Variante 1: .env Datei

Du lagerst die Passwörter in eine separate Datei aus:

$ vim ~/grafana/.env

Inhalt

GF_SECURITY_ADMIN_USER=admin
GF_SECURITY_ADMIN_PASSWORD=passwordvongrafana

In der compose.yml r⁣referenzierst sie dann so:

environment:
  - GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
  - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}

Podman Compose liest die .env Datei automatisch ein.

Der Vorteil: Du kannst die compose.yml bedenkenlos in Git einchecken oder weitergeben – solange die .env Datei nicht dabei ist.

echo ".env" >> .gitignore

Variante 2: Podman Secrets

Podman hat einen eingebauten Mechanismus für Geheimnisse. Die Daten werden verschlüsselt gespeichert:

echo "passwordvongrafana" | podman secret create grafana_password -

In der Quadlet-Datei:

Secret=grafana_password,type=env,target=GF_SECURITY_ADMIN_PASSWORD

Zeit gespart? Dann unterstütze doch it-zeugs.de

Wenn dieser Tipp dir geholfen hat, Zeit zu sparen, überlege bitte, eine kleine Spende zu hinterlassen. Dein Beitrag hilft mir, weiterhin wertvolle Inhalte zu erstellen. Du kannst unter diesem Linke spenden: Spende it-zeugs.de

Falld du nicht spenden willst oder kannst, dann wäre es toll, wenn du deinen nächsten Amazon Einkauf mit diesem Link beginnen würdest: Amazon Link. Für dich wird es nicht teurer, ich bekomme aber einen kleinen Beitrag.

Vielen herzlichen Dank ❤️

Schreibe einen Kommentar