„Bei mir läuft’s“ ist ein toller Satz – bis jemand anderes deine Software starten muss. Container sind die Kiste, die das beheben soll, und wie bei jeder Kiste lohnt der Blick, was wirklich drinsteckt.
Kurz gesagt
Ein Container ist ein gewöhnliches Programm auf einem Linux-Rechner, das nur einen Ausschnitt des Systems sieht. Je nach Konfiguration bekommt er eigene Prozesse, ein eigenes Netz, ein eigenes Dateisystem und Grenzen für Ressourcen wie Arbeitsspeicher oder Rechenzeit. Nichts davon passiert automatisch: Wovon ein Container abgeschottet ist und wie viel er verbrauchen darf, legt seine Konfiguration fest. Die Open Container Initiative (OCI) schreibt die gemeinsamen Formate, damit Images, Laufzeitumgebungen und Registries verschiedener Hersteller zusammenpassen. Ein Container ist kein kleiner virtueller Rechner: Er teilt sich den Kernel mit dem Rechner, auf dem er läuft, und das entscheidet, wovor er dich schützen kann und wovor nicht.
So funktioniert’s
- Kernelfunktionen erledigen die Arbeit. Die OCI-Laufzeitspezifikation sagt, dass ein Linux-Container aus Funktionen des Host-Kernels gebaut wird: Namespaces, Control Groups, Capabilities, Linux Security Modules und Abschottung des Dateisystems. Der Kernel ist der Kern des Betriebssystems, der Prozesse, Speicher und Geräte verwaltet. Ein Container bringt keinen eigenen mit, er nutzt den des Hosts.
- Namespaces geben jedem Container seine eigene Sicht. Ein Namespace verpackt eine globale Systemressource so, dass die Prozesse darin eine eigene, abgeschottete Ausgabe davon vor sich zu haben scheinen. Die OCI-Spezifikation nennt acht Typen: pid (Prozess-IDs), network, mount (Einhängepunkte), ipc, uts (Rechnername), user (Benutzer- und Gruppen-IDs), cgroup und time. Ist ein Typ in der Konfiguration eines Containers nicht aufgeführt, teilt sich der Container diesen Namespace mit der Laufzeitumgebung, aus der er gestartet wurde. Das ist oft der Namespace des Hosts, muss es aber nicht sein.
- Control Groups begrenzen Ressourcen. Eine cgroup (Control Group) ordnet Prozesse in einem Baum und verteilt Systemressourcen entlang dieses Baums. Grenzen nahe der Wurzel kann weiter unten niemand aufheben. Für einen Container sind Grenzen optional: Seine Konfiguration kann sie im Feld
resourcessetzen, muss es aber nicht. - Rechte lassen sich beschneiden. Capabilities zerlegen die Allmacht des Root-Benutzers in einzelne Rechte, die sich getrennt ein- und ausschalten lassen. Die Spezifikation erlaubt es, festzulegen, welche ein Prozess behält, Systemaufrufe über seccomp (einen Sandbox-Mechanismus im Kernel) zu filtern, den Gewinn neuer Rechte zu verbieten (
noNewPrivileges), Benutzer-IDs umzuschreiben (uidMappings: „root“ im Container kann auf dem Host ein gewöhnlicher Benutzer sein) und das Root-Dateisystem schreibgeschützt einzuhängen. Ob eine Container-Software das standardmäßig einschaltet, entscheidet sie selbst. - OCI besteht aus drei Spezifikationen. Die Image-Spezifikation beschreibt, was ein Image ist: ein Manifest, ein optionaler Index (eine Liste von Manifesten, etwa für verschiedene Plattformen), Dateisystem-Schichten und eine Konfiguration. Ihr Ziel sind austauschbare Werkzeuge zum Bauen, Transportieren und Startklarmachen von Images. Die Laufzeit-Spezifikation beschreibt, wie ein vorbereitetes Bundle ausgeführt wird. Die Distributions-Spezifikation beschreibt, wie Images zu einer Registry hoch- und von dort heruntergeladen werden; eine Registry ist ein Server, der Images ablegt.
- Ein Tag zeigt, ein Digest identifiziert. Ein Tag ist ein menschenlesbarer Zeiger auf ein Manifest; ein Manifest kann null, einen oder viele Tags tragen. Ein Digest ist eine Kennung aus einem Hash über den Inhalt (empfohlen ist SHA-256) und benennt damit genau diese Bytes. Wer Inhalte aus nicht vertrauenswürdiger Quelle verwendet, soll sie gegen den Digest prüfen. Ein Tag wie
2026.916.1sagt, was der Hersteller gemeint hat; was du tatsächlich bekommen hast, sagt nur der Digest. - Image, Container, Volume. Das Image ist die Vorlage, der Container eine laufende Instanz daraus, ein Volume Speicher außerhalb des Container-Dateisystems, der den Austausch des Containers überlebt. Laut Spezifikation lässt sich das Root-Dateisystem schreibgeschützt einhängen; veränderliche Daten gehören daher in Volumes oder externe Dienste.
In der Praxis
Ein Container ist ein Prozess mit anderer Sicht, und den Unterschied kannst du selbst nachsehen:
readlink /proc/self/ns/pid # auf dem Host
docker exec CONTAINER readlink /proc/self/ns/pid # im Container
docker ps --format '{{.Names}} {{.Image}}' # welches Image mit welchem Tag wo läuft
docker image inspect --format '{{.RepoDigests}}' IMAGE # Digest(s) eines aus einer Registry geladenen ImagesZwei verschiedene Nummern in den ersten beiden Zeilen heißen: zwei verschiedene pid-Namespaces. (readlink muss im Image vorhanden sein; schlanke Images haben es mitunter nicht.) Ein Beispiel aus dem Bytearium-Inventar (Lesung vom 14. Okt. 2026): Auf der Docker-VM liefen 18 von 22 Containern, und der Paperclip-Container ist mit dem Image ghcr.io/paperclipai/paperclip:2026.916.1 verzeichnet, also mit Name und Tag. Ob der Stack zusätzlich einen Digest festschreibt, steht nicht im Inventar, und das ist der erste Blick, der sich lohnt.
Drei Gewohnheiten, die einen Container-Host langweilig halten
Erstens: Gib jedem Container ein Speicherlimit und eine Neustartregel, damit ein durchdrehender Prozess nicht den Host mitreißt und ein abgestürzter Dienst ohne dich zurückkommt. Zweitens: Halte Konfiguration in Dateien neben der Compose-Definition und Daten in benannten Volumes oder Bind-Mounts, die du sicherst; der Container selbst muss wegwerfbar sein. Drittens: Pinne Images per Digest für alles, worauf du angewiesen bist, und aktualisiere nach einem Plan, den du bestimmst, statt nach dem, was latest heute gerade bedeutet. Ein Host, auf dem jeder Container in einer Minute aus dem Repository gelöscht und neu erzeugt werden kann, ist ein Host, den du ohne Angst aktualisieren kannst.
Prüfliste
- Notiere zu jedem laufenden Container Image, Tag und Digest; ein Tag allein sagt nicht, welcher Build läuft.
- Prüfe, woher ein Image stammt, bevor du es lädst, und kontrolliere den Digest, wenn du einen festschreibst.
- Lege fest, welche Daten den Austausch eines Containers überleben müssen, lege sie in ein Volume oder einen externen Dienst und nimm sie ins Backup auf.
- Starte Container als normaler Benutzer, wo das Image es zulässt, streiche Capabilities, die du nicht brauchst, und hänge das Root-Dateisystem schreibgeschützt ein, wo es geht.
- Patche den Host so ernsthaft wie die Images, denn Container teilen sich den Kernel des Hosts.
- Plane, wie du ein Image aktualisierst und wie du auf das vorherige zurückgehst.