Container vereinfachen den Test und Betrieb von Server-Diensten. Ein Container verpackt eine Software zusammen mit all ihren Abhängigkeiten in eine (transportable) Einheit.
Software läuft selten isoliert. Sie benötigt eine spezifische Umgebung:
Laufzeitumgebungen (Runtimes): z. B. Python 3.11, Java 17 oder Node.js.
Bibliotheken: Sammlungen von Hilfsfunktionen (z. B. für Verschlüsselung oder Grafik).
System-Tools: Programme für die Netzwerkkommunikation oder Dateiverarbeitung.
Konfigurationen: Pfade, Umgebungsvariablen oder Zeitzoneneinstellungen.
Fehlt nur eine dieser Komponenten oder liegt sie in einer falschen Version vor, startet die Software nicht ("Dependency Hell").
In der klassischen Entwicklung tritt oft die "Umgebungsdrift" auf: Software funktioniert auf dem Laptop, scheitert aber im Rechenzentrum aufgrund minimaler Unterschiede im Betriebssystem. Container lösen dies durch Kapselung.
Lösung der „Dependency Hell“: Da das Container-Image unveränderlich (immutable) ist, verhält sich die Anwendung in der Testumgebung exakt so wie in der Produktion.
Architekturmodell Microservices: Anwendungen werden nicht mehr als riesige "Monolithen" gebaut, sondern in kleine, lose gekoppelte Einheiten zerlegt. Container ermöglichen es, diese Bausteine unabhängig voneinander zu entwickeln und zu aktualisieren.
Effizienz in CI/CD-Pipelines: Testumgebungen können in Sekunden automatisiert auf- und abgebaut werden. Das beschleunigt den Zyklus von der Code-Änderung bis zur Veröffentlichung (Feedback-Loop).
Für Administrator*innen bieten Container entscheidende Vorteile bei der Verwaltung von Servern:
Portabilität: Ein OCI-konformer Container läuft überall dort, wo eine Container-Engine (wie Podman) installiert ist – egal ob auf einem lokalen Server, im Mainframe oder in der Cloud.
Skalierbarkeit: Bei hoher Last (z. B. ein Ansturm auf einen Webshop) können binnen Millisekunden zusätzliche Instanzen derselben Anwendung gestartet werden.
Saubere Host-Systeme: Da alle Bibliotheken im Container liegen, muss auf dem Host-Server kaum noch Software installiert werden. Das Betriebssystem bleibt "schlank" und stabil.
Einfaches Rollback: Wenn ein Update fehlschlägt, stoppt man einfach den neuen Container und startet den alten wieder. Der Zustand davor ist sofort wiederhergestellt.
Ein oft unterschätzter Use-Case ist die Sicherheit durch Prozess-Isolation:
Wenn eine Anwendung in einem Container kompromittiert wird, bleibt der Angreifer (bei korrekter Konfiguration) im Container gefangen. Er sieht keine Dateien des Hosts und keine anderen Prozesse.
Podman-Besonderheit: Da Podman "Rootless" (ohne Administrator*innenrechte) laufen kann, hat ein Angreifer selbst bei einem Ausbruch aus dem Container keine Root-Rechte auf dem echten Server.
Ein Container ist kein monolithisches Produkt, sondern ein geschicktes Zusammenspiel nativer Linux-Kernel-Features. Man spricht auch von OS-Level Virtualization.
chroot (1979): Der „Urahn“ der Isolation. Er ändert das Root-Verzeichnis für einen Prozess. Dieser sieht nur noch die Dateien innerhalb eines festgelegten Unterordners und hält diesen für das gesamte System (/).cgroups): Sie regeln, was ein Prozess nutzen darf. Mit cgroups werden Ressourcen wie CPU, Arbeitsspeicher (RAM) und Festplatten-I/O begrenzt. Dies verhindert, dass ein einzelner Container (z. B. durch einen Programmierfehler) den gesamten Host-Server lahmlegt („Noisy Neighbor“-Problem).Docker war 2013 der erste populäre „Überbau“, der diese komplexen Kernel-Technologien unter einer einfachen Oberfläche zusammenführte und durch ein standardisiertes Image-Format massentauglich machte. Heute folgen moderne Tools wie Podman denselben Prinzipien, setzen dabei aber auf eine noch stärkere Integration in moderne Linux-Sicherheitsfeatures.
Die Open Container Initiative (OCI) wurde 2015 gegründet, um offene, herstellerunabhängige Industriestandards für Container-Formate und Laufzeiten zu schaffen. Ziel war es, die Abhängigkeit von einer einzelnen Firma (Vendor Lock-in) zu verhindern und Interoperabilität sicherzustellen.
Man kann sich den OCI-Standard wie die Normierung von Schiffscontainern vorstellen: Es ist egal, wer den Container gebaut hat oder welcher Kran ihn hebt – sie passen immer zusammen.
Die drei zentralen Spezifikationen:
Image Specification (image-spec): Definiert das Format der Container-Images. Ein OCI-Image ist im Kern ein strukturiertes Tar-Archiv, das die Dateisystem-Layer und Metadaten (wie Startbefehle oder Umgebungsvariablen) enthält.
Runtime Specification (runtime-spec): Legt fest, wie ein Container ausgeführt wird. Sie beschreibt den Lebenszyklus (Starten, Stoppen, Löschen) und die Konfiguration, mit der die Host-Ressourcen isoliert werden.
Distribution Specification (dist-spec): Standardisiert den Austausch von Images zwischen Clients (wie Podman) und Servern (Registries wie Docker Hub oder Quay.io).
Dank OCI ist die Container-Welt austauschbar geworden:
Ein Image, das mit Docker erstellt wurde, kann problemlos mit Podman gestartet werden.
Werkzeuge können spezialisiert werden: Während Docker ein "All-in-one"-Tool ist, nutzt Podman im Hintergrund oft die OCI-Referenz-Runtime runc, um die eigentliche Arbeit im Kernel zu erledigen.
Fazit: OCI sorgt dafür, dass Container-Technologie eine universelle Infrastruktur-Eigenschaft geworden ist (ähnlich wie TCP/IP für das Internet) und kein proprietäres Produkt bleibt.
In der Welt der Container unterscheiden wir strikt zwischen dem „Bauplan“ und der „Ausführung“.
Allgemein versteht man unter einem Image (Abbild) in der Informatik eine statische Datei, die den vollständigen Zustand eines Systems oder Datenträgers zu einem bestimmten Zeitpunkt speichert (ähnlich wie eine ISO-Datei einer DVD oder ein Backup-Image einer Festplatte).
Ein Container-Image ist ein spezielles, schreibgeschütztes (read-only) Paket, das alles enthält, was zum Ausführen einer Anwendung benötigt wird:
Der ausführbare Programmcode.
Die benötigten Laufzeitumgebungen und Bibliotheken.
Standard-Konfigurationen und Umgebungsvariablen.
Das Besondere: Ein Container-Image besteht aus verschiedenen Layern (Schichten). Wenn zwei verschiedene Images die gleiche Basis nutzen (z. B. das Betriebssystem Alpine Linux), müssen diese gemeinsamen Schichten nur einmal auf der Festplatte gespeichert werden.
Ein Container ist die lebendige Instanz eines Images. Wenn man ein Image startet, wird es in den Arbeitsspeicher geladen und als isolierter Prozess ausgeführt.
Man kann sich das Verhältnis wie in der objektorientierten Programmierung vorstellen:
pull-Befehl. Sie verbrauchen Platz, tun aber noch nichts.run-Befehl weist dem Image Ressourcen zu und startet es als isolierten Prozess im Kernel.Um den Unterschied zwischen Images und Containern zu verstehen, hilft ein Blick auf die grundlegenden Befehle. Podman folgt hierbei der intuitiven Syntax, die durch Docker etabliert wurde.
Diese Befehle verwalten die statischen Baupläne auf deiner Festplatte.
podman pull <image>: Lädt ein fertiges Abbild aus einer Registry (z. B. Docker Hub) herunter.podman images: Listet alle lokal gespeicherten Images auf. Man sieht hier die Größe und die Image-ID.podman rmi <image>: Löscht ein Image von der Festplatte (remove image).Diese Befehle steuern die aktiven (oder gestoppten) Instanzen.
podman run <image>: Der wichtigste Befehl. Er erzeugt aus einem Image einen neuen Container und startet ihn sofort.podman ps: Zeigt alle aktuell laufenden Container an.podman ps -a: Zeigt alle Container an (auch die bereits beendeten oder abgestürzten).podman stop <container_id>: Hält einen laufenden Prozess im Container an.podman rm <container_id>: Löscht die Instanz des Containers (die beschreibbare Schicht wird vernichtet).pull: Registry $\rightarrow$ Local Storagerun: Local Storage $\rightarrow$ Runtime/ContainerEin wichtiges Konzept von Containern ist ihre Flüchtigkeit (Ephemerality). Ein Container ist kein dauerhafter Server, sondern ein Prozess, der jederzeit ersetzt werden kann.
Wenn ein Container gestartet wird, liegt über dem schreibgeschützten Image eine dünne, beschreibbare Schicht (Container Layer).
Alle Änderungen (neue Dateien, Datenbankeinträge) landen in dieser Schicht.
Aber: Wird der Container mit podman rm gelöscht, wird auch diese Schicht gelöscht. Die Daten sind unwiderruflich verloren.
Um Daten dauerhaft (persistent) zu speichern, nutzt man Volumes. Dabei wird ein Verzeichnis des Host-Rechners in den Container "eingeblendet" (gemountet).
Mehr dazu: Wie Volumes konkret konfiguriert werden – benannte Volumes gegenüber Bind-Mounts, Persistenz über Neustarts hinweg und die Optionen wie
:rooder:Z– zeigt ausführlich der Abschnitt Volumes in Compose.
podman version
podman info
podman run hello-world
Wir nutzen Alpine Linux, eine extrem kleine und schnelle Linux-Distribution.
podman run -it alpine /bin/sh
podman run: Erstellt und startet einen Container.-i (interactive): Hält die Standardeingabe (STDIN) offen, auch wenn kein Terminal zugewiesen ist.-t (terminal/tty): Weist dem Container ein Pseudo-Terminal zu. Nur mit -it kannst du interaktiv mit dem Container kommunizieren.alpine: Das Image, das als Basis dient. Wenn es lokal nicht vorhanden ist, lädt Podman es automatisch herunter./bin/sh: Der Befehl, der im Container ausgeführt werden soll – in diesem Fall die Shell.Hinweis: Bei der Minimal-Installation ist keine bash-Shell verfügbar.
Dann z.B.:
whoami
ls /
exit
Erzeugen eines Volume mit podman volume create website
podman volume inspect websiteStarten eines Container mit einem nginx-Webserver
podman run --name mein-webserver -d \
-v website:/usr/share/nginx/html:Z \
-p 8180:80 \
docker.io/library/nginx
-p 8180 leitet den Port auf der lokalen Maschine auf den Port 80 im Container weiter.
-v übergibt das Volume
-d startet den Container im Hintergrund
Mit podman exec -it mein-webserver bash kann man sich auf dem Container einloggen.
echo "<h1>Willkommen an der HTW!</h1>" > /usr/share/nginx/html/index.html
Im Browser des Hosts http://localhost:8180
execvs.run: Beide Befehle können eine interaktive Shell öffnen, tun aber Grundverschiedenes.
podman run -it <image> /bin/sh(siehe Alpine-Beispiel oben) erzeugt einen neuen Container aus einem Image und startet darin die Shell als Hauptprozess. Beendet man die Shell mitexit, stoppt der Container.podman exec -it <container> bashstartet einen zusätzlichen Prozess in einem bereits laufenden Container (hier der im Hintergrund laufendemein-webserver). Mitexitverlässt man nur die Shell – der Container läuft weiter.Kurz:
runstartet einen Container,execsteigt in einen laufenden ein.-it(interactive + tty) ist in beiden Fällen nötig, um interaktiv arbeiten zu können.
Container löschen:
podman stop mein-webserver
podman rm mein-webserver
Fehlersuche z.B. mit:
podman logs mein-webserver
podman ps
Hinweis: Dasselbe Volume lässt sich auch in einer
compose.yamldeklarativ einbinden – inklusive der hier verwendeten SELinux-Option:Z. Siehe Volumes in Compose.
Ansehen aller (auch nicht laufender mittels -a) Container
podman ps -aStarten eines Containers mit eventuellem Herunterladen aus dem Docker-Hub:
podman run <image-name>Beenden von Containern
podman kill <container-name>Docker Version anzeigen:
podman --versionHeruntergeladene Images anzeigen:
podman image lsLöschen der Images, die nicht verwendet werden:
podman image pruneErzeugen eines Volume:
podman volume create <volume-name>Alle Container anhalten. Beachten Sie die Verwendung von Command Substitution:
podman stop $(podman ps -a -q)
In der Praxis besteht eine Anwendung selten aus nur einem einzigen Container. Compose ist das Werkzeug, um mehrere Container gemeinsam zu definieren, zu starten und zu stoppen – deklarativ in einer einzigen compose.yaml.
Eine ausführliche Behandlung – Dateiformat, Befehle, Netzwerke, Volumes, .env-Dateien und YAML-Besonderheiten – findet sich im nächsten Kapitel:
In der professionellen Softwareentwicklung werden Images oft auch selbst erstellt, um eigene Anwendungen mitsamt ihrer Laufzeitumgebung zu paketieren. Podman ermöglicht diesen Prozess durch eine automatisierte Bauanleitung.
Die Basis für jedes Image ist das Containerfile. Dabei handelt es sich um eine einfache Textdatei, die schrittweise definiert, wie das Image aufgebaut sein soll. Sie legt fest, welches Basis-Betriebssystem verwendet wird, welche Softwarepakete installiert werden müssen und welche Programmdateien in das Image kopiert werden sollen.
Mit dem Befehl podman build wird dieses File verarbeitet. Jede Zeile in der Anleitung erzeugt eine neue, unveränderliche Schicht (Layer) im resultierenden Image.
Vorteile dieses Verfahrens:
Podman ist ein hervorragendes Werkzeug, um Container auf einem einzelnen Rechner (z. B. deinem Laptop) zu verwalten. In der realen Welt laufen Anwendungen jedoch oft auf riesigen Server-Clustern. Hier stößt die manuelle Verwaltung an Grenzen.
Kubernetes (oft abgekürzt als K8s) ist das Betriebssystem für solche Cluster. Es fungiert als „Dirigent“ (Orchestrator) für Container.
Scheduling: K8s entscheidet automatisch, auf welchem physischen Server noch genug Platz (CPU/RAM) ist, um einen neuen Container zu starten.
Self-Healing: Wenn ein Container abstürzt oder ein ganzer Server ausfällt, merkt Kubernetes das sofort und startet die betroffenen Container auf einem anderen Server neu.
Skalierung: Bei hohem Besucheraufkommen kann Kubernetes angewiesen werden, die Anzahl der laufenden Container-Instanzen automatisch zu erhöhen (Horizontal Scaling).
Service Discovery & Load Balancing: Kubernetes verteilt den eingehenden Datenverkehr automatisch auf die verfügbaren Instanzen einer Anwendung.
Podman wurde so entwickelt, dass es sehr nah an den Konzepten von Kubernetes arbeitet. Ein wichtiges Merkmal von Podman ist die Fähigkeit, sogenannte Pods zu erstellen. Ein Pod ist eine Gruppe von einem oder mehreren Containern, die sich Ressourcen teilen – genau die kleinste Einheit, die auch in Kubernetes verwaltet wird.
Merksatz:
Wenn Podman das Werkzeug ist, um einen einzelnen Motor (Container) zu warten, dann ist Kubernetes die Leitzentrale, die eine ganze Flotte von LKWs koordiniert.