Ein Container ist kein kleiner Server und ein Image kein Backup. Technisch führt eine Containerlaufzeit gewöhnliche Prozesse mit einem vorbereiteten Dateisystem, isolierten Sichten auf Kernelressourcen und gesetzten Ressourcen- und Sicherheitsgrenzen aus. Der Hostkernel bleibt Teil jeder Operation. Diese Architektur macht Anwendungsumgebungen reproduzierbar und schnell ersetzbar; sie verschiebt aber Verantwortung in Imageherkunft, Runtime, Netzwerk, Persistenz, Secrets, Ressourcensteuerung und Orchestrierung.
Für Admins ist die wichtigste Trennung jene zwischen Artefakt, Laufzeitinstanz und Betriebszustand. Ein Image beschreibt das startbare Dateisystem und Metadaten. Ein Container ist eine konkrete Ausführung. Datenbanken, Queues, Schlüssel, Konfiguration und Auditdaten besitzen eigene Lebenszyklen. Wer diese Ebenen gemeinsam als «den Docker-Container» behandelt, kann weder eine Störung eingrenzen noch einen Restore vollständig planen.
Die Erklärung beginnt beim Image als auslieferbarem Artefakt und folgt seinem Weg über Engine und Runtime bis zu Kernel, Netzwerk und Storage. Orchestrierung, Sicherheit, Diagnose und Recovery bauen auf diesem Ablauf auf.
Passende Befehle
Fertige Befehle rund um Docker für PowerShell und die Unix-Shell, mit Beispielen zum Kopieren.
Beiträge zu Docker (1)
Technische Einordnung
NIST beschreibt Anwendungscontainer als Form von Betriebssystemvirtualisierung: Anwendungen teilen den Kernel, während Isolation und Ressourcensteuerung auf Betriebssystemmechanismen beruhen. Virtuelle Maschinen virtualisieren dagegen Hardware für einen eigenen Gastkernel. Container und VMs können kombiniert werden; die Wahl verändert Angriffsfläche, Kompatibilität, Startkosten und Ausfallbereich (NIST SP 800-190 – Application Container Security Guide).
Ein typischer Linux-Pfad besteht aus:
- Registry oder lokalem Content Store mit OCI-Manifesten, Konfigurationen und Layers;
- Engine oder Orchestrator, der gewünschten Zustand, Netzwerk, Mounts und Policy bestimmt;
- High-Level-Runtime wie
containerdoder CRI-O für Image- und Containerverwaltung; - OCI-Runtime wie
runc, die aus Bundle undconfig.jsonden Prozess erzeugt; - Hostkernel mit Namespaces, cgroups, Capabilities, Seccomp und einem Linux Security Module;
- Containerprozessen, die über virtuelle oder gemountete Dateisysteme, Sockets und Geräte mit ihrer Umgebung interagieren.
Die Open Container Initiative standardisiert Image-, Runtime- und Distributionsteile getrennt. Dadurch kann ein OCI-Image durch verschiedene Engines und Runtimes verarbeitet werden, ohne dass Netzwerk, Orchestrierung oder Datensicherung automatisch standardisiert wären (OCI Image Specification, OCI Runtime Specification, OCI Distribution Specification).
Image: Manifest, Konfiguration und Layers
Ein OCI-Image ist ein gerichteter Inhaltsgraph. Ein Manifest verweist über Deskriptoren und kryptografische Digests auf eine Image-Konfiguration und geordnete Dateisystem-Layers. Ein optionaler Image Index kann mehrere Manifeste für unterschiedliche Betriebssysteme und Architekturen bündeln. Media Type, Digest und Grösse sind Teil des Deskriptors; Tags gehören dagegen zur Registry-Namensauflösung und sind keine unveränderliche Identität (OCI Image Manifest, OCI Image Configuration).
Layers enthalten Dateisystemänderungen. Beim Start werden sie über einen Storage Driver zu einer gemeinsamen Root-Sicht zusammengesetzt und durch einen beschreibbaren Containerlayer ergänzt. Ein gelöschter Secret- oder Paketinhalt kann in einem früheren Layer weiter vorhanden sein. Multi-Stage Builds reduzieren Buildwerkzeuge und Zwischenartefakte im finalen Image, ersetzen aber keine Secret- und Herkunftsprüfung (Docker – Storage drivers, Docker – Multi-stage builds).
Tags, Digests und Plattformauswahl
Ein Tag wie stable, 3 oder latest kann auf einen anderen Manifestdigest verschoben werden. Reproduzierbare Produktion pinnt deshalb den freigegebenen Digest oder dokumentiert mindestens den beim Rollout aufgelösten Digest. Bei Multi-Arch-Images wählt der Client aus dem Index eine Plattform; falsche Architektur, fehlende CPU-Features oder Emulation können trotz identischem Tag zu anderem Verhalten führen.
Ein Digest beantwortet «welche Bytes?», nicht «wer hat sie gebaut?» oder «sind sie sicher?». Signaturen und Attestations können Identität, Buildherkunft und Materialien binden. SLSA beschreibt Provenance als nachprüfbare Information darüber, wo, wann und wie ein Artefakt erzeugt wurde; Sigstores cosign kann Containerartefakte signieren und verifizieren (SLSA Specification, Sigstore cosign).
$image = $env:CONTAINER_IMAGE
docker buildx imagetools inspect $image
docker image inspect $image --format '{{json .RepoDigests}}'
cosign verify $image --certificate-identity $env:EXPECTED_IDENTITY `
--certificate-oidc-issuer $env:EXPECTED_ISSUER
image="$CONTAINER_IMAGE"
docker buildx imagetools inspect "$image"
docker image inspect "$image" --format '{{json .RepoDigests}}' | jq .
cosign verify "$image" --certificate-identity "$EXPECTED_IDENTITY" \
--certificate-oidc-issuer "$EXPECTED_ISSUER"
docker buildx imagetools inspect zeigt Manifestlisten und Plattformen, docker image inspect lokale Image-Metadaten. cosign verify prüft Signatur und erwartete Identität; jq formatiert im Unix-Beispiel JSON.
Aus dem unveränderlichen Image erzeugt die Runtime den tatsächlich laufenden Container. Erst dabei kommen Writable Layer, Namespaces, cgroups, Mounts und Prozessparameter zusammen.
Runtime, Bundle und Container-Lifecycle
Die OCI Runtime Specification beschreibt einen Container als Umgebung für einen Prozess. Ein Bundle enthält config.json und ein Root-Dateisystem. Die Konfiguration legt Prozessargumente, Umgebung, Benutzer, Mounts, Namespaces, Ressourcen und weitere Plattformoptionen fest. Der Lifecycle unterscheidet Erzeugen, Starten, Beenden und Löschen; ein Prozess mit Status created läuft noch nicht (OCI Runtime Specification).
runc ist eine Referenzimplementierung dieser Low-Level-Schnittstelle. containerd verwaltet darüber Images, Snapshots, Container, Tasks und Events. Docker Engine bietet eine höhere API mit Netzwerk, Volumes, Build- und Bedienmodell. Kubernetes kommuniziert auf einem Node über das Container Runtime Interface (CRI) mit einer kompatiblen Runtime; kubelet spricht nicht einfach die Docker-CLI an (runc, containerd, Kubernetes – Container Runtime Interface).
Diese Schichten besitzen getrennte Zustände. Ein Kubernetes Pod kann Running melden, während ein Containerprozess in einer Restartschleife steckt; eine Engine kann einen Container kennen, dessen Runtime-Task nicht mehr lebt; ein Prozess kann laufen, während der Dienst keinen Traffic annimmt. Diagnose beginnt daher mit der Frage: Desired State, Engineobjekt, Runtime-Task, Prozess oder Anwendung?
Namespaces: isolierte Sicht, keine eigene Maschine
Linux-Namespaces isolieren globale Ressourcen in getrennte Sichten. Die Kernel-Manpages nennen unter anderem Mount-, PID-, Network-, IPC-, UTS-, User-, cgroup- und Time-Namespaces. Ein Prozess kann in jeder Namespaceart Mitglied genau eines Namespace sein; Beziehungen lassen sich über /proc/<pid>/ns untersuchen (namespaces(7)).
| Namespace | Isolierte Sicht | Adminrelevanz |
|---|---|---|
| Mount | Mountpunkte und Root-Dateisystem | Bind Mounts, Propagation, maskierte Hostpfade |
| PID | Prozess-IDs und Hierarchie | PID 1, Signal- und Reapingverhalten |
| Network | Interfaces, Routen, Ports, Firewallzustand | Container kann intern lauschen, ohne extern erreichbar zu sein |
| UTS | Host- und Domainname | kosmetische Identität, nicht DNS oder Security Principal |
| IPC | System-V-IPC und POSIX Message Queues | gemeinsame IPC nur bei expliziter Konfiguration |
| User | Abbildung von UIDs/GIDs | Container-Root kann ausserhalb unprivilegiert abgebildet werden |
| cgroup | Sicht auf cgroup-Hierarchie | verhindert nicht allein Ressourcennutzung |
| Time | ausgewählte monotone/boot Zeitoffsets | selten genutzt; keine allgemeine Zeitzonenisolation |
Isolation ist konfigurierbar. Host-Netzwerk, Host-PID, --privileged, Gerätefreigaben, breite Bind Mounts oder zusätzliche Capabilities öffnen gezielt Grenzen. Der Containername und eine interne UID sind kein Security Principal über Host, Registry und Orchestrator hinweg.
PID 1, Signale und sauberes Beenden
Im PID-Namespace übernimmt der erste Prozess besondere Aufgaben. Er empfängt Signale anders und muss verwaiste Kindprozesse einsammeln. Shellwrapper, die das eigentliche Programm nicht mit exec starten, können Terminationssignale verschlucken. Orchestratoren senden üblicherweise zuerst ein Terminationssignal, warten eine Grace Period und erzwingen danach das Ende. Die Anwendung muss neue Arbeit stoppen, laufende Operationen begrenzt abschliessen und Zustände flushen.
Docker kann mit --init einen kleinen Initprozess einsetzen; dies repariert keine Anwendung, macht Signalweiterleitung und Child-Reaping aber expliziter (Docker run reference – --init). Bei Mailqueues, Datenbanken und Indexern gehört die maximal sichere Shutdownzeit in das Deploymentmodell.
cgroups: Steuerung und Abrechnung
cgroups gruppieren Prozesse und wenden Controller für Ressourcen an. In cgroup v2 bilden Prozesse eine einheitliche Hierarchie. CPU-, Memory-, I/O- und PID-Controller besitzen unterschiedliche Semantik: Ein CPUlimit drosselt, ein Memorylimit kann einen OOM-Kill auslösen, ein PIDlimit verhindert neue Prozesse oder Threads, und I/O-Limits hängen vom tatsächlichen Blockgerätepfad ab (Linux kernel – Control Group v2).
Request/Reservation und Limit dürfen nicht verwechselt werden. Kubernetes verwendet Requests für Scheduling und Limits für Laufzeitgrenzen; bei Memory ist das Limit reaktiv und wird unter Druck durch den Kernel durchgesetzt. Ein Pod kann trotz genügend Gesamtkapazität wegen Node- oder cgroup-Druck evicted oder beendet werden (Kubernetes – Resource Management for Pods and Containers).
docker container inspect $env:CONTAINER_NAME --format '{{json .State}}'
docker container top $env:CONTAINER_NAME
docker stats --no-stream $env:CONTAINER_NAME
Get-Process -Name $env:HOST_PROCESS_NAME -ErrorAction SilentlyContinue
docker container inspect "$CONTAINER_NAME" --format '{{json .State}}' | jq .
docker container top "$CONTAINER_NAME"
docker stats --no-stream "$CONTAINER_NAME"
pid="$(docker inspect --format '{{.State.Pid}}' "$CONTAINER_NAME")"
ps -o pid,ppid,user,stat,args -p "$pid"
docker container inspect zeigt Konfiguration und Runtimezustand, docker container top die Prozesssicht und docker stats laufende Ressourcenwerte. Get-Process und ps prüfen den Hostprozess; Host-PID und Container-PID können verschieden sein.
Capabilities, Seccomp und Linux Security Modules
Linux zerlegt klassische Rootprivilegien in Capabilities. CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_SYS_ADMIN oder CAP_SYS_PTRACE öffnen sehr unterschiedliche Operationen; CAP_SYS_ADMIN umfasst besonders breite Macht. Ein nicht als Root laufender Prozess kann Capabilities tragen, und ein Rootprozess kann fast alle entfernt bekommen (capabilities(7)).
Seccomp filtert Systemaufrufe. Docker verwendet standardmässig ein Profil, das ausgewählte Syscalls blockiert; unconfined entfernt diese Schicht. AppArmor oder SELinux können zusätzlich objektbezogene Zugriffe begrenzen. Diese Kontrollen ergänzen sich: eine Capability erlaubt eine Operationsklasse, Seccomp kann den zugehörigen Syscall sperren, und das Security Module kann den Zugriff auf ein konkretes Objekt verweigern (Docker – Seccomp security profiles, Docker – AppArmor security profiles).
--privileged ist keine bequeme Fehlerbehebung. Es erweitert Geräte- und Capabilityzugriff und lockert Sicherheitsprofile. Wenn eine Anwendung nur einen Port, ein einzelnes Gerät oder einen Read-only-Pfad benötigt, wird genau diese Fähigkeit freigegeben und im Threat Model begründet.
Root, User Namespaces und Rootless-Betrieb
UID 0 im Container ist ohne User Namespace dieselbe numerische UID 0, die der Hostkernel beurteilt. Namespaces begrenzen Sicht und Operationen, aber ein Kernel- oder Konfigurationsfehler trifft weiterhin den Host. Ein User Namespace kann Container-UIDs auf unprivilegierte Host-UIDs abbilden; Rootless Engines betreiben Daemon und Container ohne Hostroot (user_namespaces(7), Docker – Rootless mode).
Rootless verändert Netzwerk, Portbindung, cgroup- und Storagevoraussetzungen und ist deshalb ein Betriebsmodell, kein universeller Härtungsschalter. Unabhängig davon gelten: nicht benötigte Capabilities entfernen, Root-Dateisystem read-only betreiben, schreibbare Pfade einzeln mounten, no-new-privileges setzen und Runtime-Socket nicht in Workloads einbinden. Zugriff auf Docker- oder CRI-Socket ist faktisch Zugriff auf die Host-Control-Plane.
Nach Prozess- und Rechteisolation folgt die Erreichbarkeit. Ein eigener Network Namespace schafft zunächst nur eine getrennte Sicht; Routing, Namensauflösung und veröffentlichte Ports müssen zusätzlich aufgebaut werden.
Netzwerk: Namespace, CNI und Port Publishing
Ein Linux-Container besitzt je nach Modus einen eigenen Network Namespace. Eine Engine verbindet ihn häufig über ein veth-Paar mit einer Bridge und führt NAT oder Port Publishing aus. Overlaynetze kapseln Traffic zwischen Hosts; Service Proxies oder eBPF-Datenpfade verteilen virtuelle Serviceadressen. CNI standardisiert, wie eine Runtime Netzwerkplugins zum Hinzufügen und Entfernen eines Containers aus einem Netzwerk aufruft; es standardisiert nicht die gesamte Netzarchitektur eines Clusters (CNI Specification).
Vier Adressen werden getrennt dokumentiert:
- Listen Address im Prozess, etwa
127.0.0.1:8080oder0.0.0.0:8080im Namespace; - Container-/Pod-IP, deren Lebensdauer an die Instanz gekoppelt sein kann;
- Service- oder Load-Balancer-Adresse als stabilere Zugriffsschicht;
- veröffentlichte Hostadresse und Port, die Firewall, NAT und externe Erreichbarkeit bestimmen.
EXPOSE im Dockerfile veröffentlicht keinen Port; es dokumentiert lediglich vorgesehene Ports. Port Publishing ist eine Laufzeitentscheidung. Ebenso beweist ein offener Hostport nicht, dass Readiness, TLS oder Anwendungsauthentisierung funktionieren (Docker – Container networking).
docker network inspect $env:CONTAINER_NETWORK
docker container port $env:CONTAINER_NAME
Get-NetTCPConnection -State Listen | Sort-Object LocalPort
Test-NetConnection $env:SERVICE_HOST -Port $env:SERVICE_PORT
docker network inspect "$CONTAINER_NETWORK" | jq '.[0].IPAM, .[0].Containers'
docker container port "$CONTAINER_NAME"
ss -lntup
nc -vz "$SERVICE_HOST" "$SERVICE_PORT"
docker network inspect und docker container port zeigen Enginezuordnung und veröffentlichte Ports. Get-NetTCPConnection beziehungsweise ss zeigen Listener; Test-NetConnection und nc prüfen TCP. Für DNS und TLS gelten danach deren eigene Diagnosepfade.
Storage: Writable Layer, Volumes und Bind Mounts
Der beschreibbare Containerlayer gehört zur Instanz. Er ist für temporäre Laufzeitänderungen geeignet, aber weder für hohe schreibintensive Last noch als dauerhafte Datenhaltung. Docker unterscheidet Volumes, Bind Mounts, tmpfs und den Writable Layer; Volumes werden von der Engine verwaltet, Bind Mounts binden einen konkreten Hostpfad ein (Docker – Storage overview).
| Form | Eigentümer des Pfads | Typisches Risiko |
|---|---|---|
| Writable Layer | Storage Driver/Containerinstanz | Verlust beim Ersetzen; Copy-on-write- und Kapazitätskosten |
| Volume | Engine oder Volumeplugin | Name/Plugin/Hostbindung wird nicht mit Image gesichert |
| Bind Mount | Hostadministrator | Hostpfad, Rechte, SELinuxlabel und Startreihenfolge |
| tmpfs | Arbeitsspeicher | Verlust bei Stop; Memoryverbrauch und Secretreste im Swapmodell |
| externer Dienst | Datenbank, Objekt- oder Netzspeicher | Netzwerk, Identität, Konsistenz, Quota und eigener Recoveryplan |
Ein Mount überdeckt vorhandene Dateien am Zielpfad. Fehlt ein erwarteter Netzmount beim Start, kann ein Bind-Mount-Pfad auf dem lokalen Host liegen und die Anwendung unbemerkt dorthin schreiben. Ein erfolgreich gestarteter Container beweist daher nicht, dass das richtige Storagebackend aktiv ist.
Der Container Storage Interface Standard definiert eine Orchestrator-/Plugin-Schnittstelle für Volumes. Er garantiert nicht Anwendungsquieszenz, Crashkonsistenz oder erfolgreiche Restorefähigkeit. Datenbanken benötigen weiterhin ihre dokumentierten Backup- und Wiederherstellungsverfahren (Container Storage Interface Specification, Backup und Disaster Recovery).
docker container inspect $env:CONTAINER_NAME --format '{{json .Mounts}}'
docker volume inspect $env:VOLUME_NAME
docker exec $env:CONTAINER_NAME powershell -NoProfile -Command `
'Get-Volume | Select-Object DriveLetter,FileSystem,SizeRemaining,Size'
Get-PSDrive -PSProvider FileSystem
docker container inspect "$CONTAINER_NAME" --format '{{json .Mounts}}' | jq .
docker volume inspect "$VOLUME_NAME" | jq .
docker exec "$CONTAINER_NAME" findmnt --json | jq .
docker exec "$CONTAINER_NAME" df -hT
docker volume inspect liefert Volume-Driver und Mountpoint. Get-Volume, Get-PSDrive, findmnt und df prüfen die tatsächlich sichtbare Speicherlage und Kapazität.
Konfiguration und Secrets
Umgebungsvariablen sind bequem, aber häufig über Inspect-Ausgaben, Prozessumgebung, Crashreports oder Supportbundles sichtbar. Ein Secretobjekt in einem Orchestrator ist zudem nicht automatisch verschlüsselt, rotiert oder vor privilegierten Nodeadministratoren verborgen. Kubernetes dokumentiert ausdrücklich, dass Secrets standardmässig unverschlüsselt in etcd gespeichert werden, sofern Encryption at Rest nicht konfiguriert ist (Kubernetes – Secrets).
Konfiguration wird in vier Klassen inventarisiert:
- nicht-sensitive, versionierbare Deploymentkonfiguration;
- Secretreferenzen und ihre externe Quelle;
- zur Laufzeit erzeugter Zustand wie Hostkeys, Datenbankschemas oder interne CAs;
- Imageeingebaute Defaults, die bei Updates wechseln können.
Rotation ist eine Zustandsmaschine: neues Secret bereitstellen, Consumer aktualisieren oder neu laden, Funktionsnachweis führen, altes Secret widerrufen und Caches beziehungsweise langlebige Verbindungen berücksichtigen. Ein Containerrestart allein garantiert keine Rotation im entfernten Dienst.
Health, Readiness, Liveness und Startup
Prozesszustand, Dienstbereitschaft und fachliche Gesundheit sind verschiedene Signale. Docker HEALTHCHECK führt einen Befehl im Container aus und speichert Exitcode und begrenzte Ausgabe. Kubernetes unterscheidet Startup-, Readiness- und Liveness-Probes: Startup schützt langsamen Start vor vorzeitiger Liveness, Readiness steuert Endpoints, Liveness kann einen Restart auslösen (Dockerfile reference – HEALTHCHECK, Kubernetes – Configure Liveness, Readiness and Startup Probes).
Eine gute Probe ist billig, zeitlich begrenzt und beantwortet genau eine Betriebsfrage. Eine Liveness-Probe darf nicht bei jeder externen Teilstörung Restarts auslösen; sonst verstärkt sie DNS-, Datenbank- oder Providerprobleme. Eine Readiness-Probe darf den Dienst aus dem Traffic nehmen, wenn er keine neue Arbeit sicher annehmen kann. Tiefgehende End-to-End-Prüfungen gehören eher ins Monitoring als in sekündliche lokale Probes.
Compose depends_on steuert Erstellungs- und Startreihenfolge; mit Bedingungen kann es auf Health oder einen erfolgreich beendeten Abhängigkeitsjob warten. Es ersetzt keine Wiederverbindungslogik: Dienste werden auch nach dem Start unabhängig ausfallen (Docker Compose – Control startup order).
docker container inspect $env:CONTAINER_NAME --format '{{json .State.Health}}'
docker container logs --since 30m --timestamps $env:CONTAINER_NAME
docker events --since 30m --filter "container=$env:CONTAINER_NAME"
docker compose ps --all
docker container inspect "$CONTAINER_NAME" --format '{{json .State.Health}}' | jq .
docker container logs --since 30m --timestamps "$CONTAINER_NAME"
docker events --since 30m --filter "container=$CONTAINER_NAME"
journalctl --unit docker --since '-30 minutes' --no-pager
docker container logs liest den konfigurierten Loggingpfad, docker events Engineereignisse und docker compose ps den Composezustand. journalctl zeigt unter systemd den Daemonkontext. Docker dokumentiert Logging Drivers, Rotation und Dual Logging separat; unbegrenzte JSON-Logs können den Host füllen (Docker – Configure logging drivers).
Healthchecks können einen fehlerhaften Prozess erkennen und ein Orchestrator kann ihn neu starten. Verlorene Daten, falsche Konfiguration oder eine kaputte externe Abhängigkeit werden dadurch jedoch nicht repariert.
Restart ist keine Recoverystrategie
Restart Policies reagieren auf Prozessende. Sie kennen weder beschädigte Daten noch blockierte Queues oder falsche Credentials. Docker weist ausserdem darauf hin, dass eine Restart Policy erst wirksam wird, wenn ein Container mindestens zehn Sekunden erfolgreich lief; manuelle Stopps unterdrücken sie bis zum Daemonrestart oder manuellen Start (Docker – Start containers automatically).
Restartschleifen verbrauchen CPU, erzeugen Logs und können abhängige Dienste überlasten. Orchestratoren verwenden Backoff, aber der Admin benötigt trotzdem ersten Fehler, Exitcode, OOM-/Evictiongrund, letzte Konfiguration und Ereigniszeitachse. Ein CrashLoop ist ein Symptomzustand, keine Ursache.
Orchestrierung: Pod, Node und gewünschter Zustand
Kubernetes gruppiert einen oder mehrere Container in einem Pod. Container eines Pods teilen Netzwerknamespace und können Volumes teilen; sie werden gemeinsam geplant. Deployments verwalten ReplicaSets und gestufte Updates. kubelet setzt auf dem Node den Podspec über CRI, CNI und Storageplugins um (Kubernetes – Pods, Kubernetes – Deployments).
| Ebene | Eigentümer | Typische Störung |
|---|---|---|
| Control Plane | API, Scheduler, Controller | gewünschter Zustand wird nicht berechnet oder geplant |
| Node/kubelet | lokale Umsetzung | Imagepull, Disk/PID/Memory Pressure, Runtime- oder CNI-Fehler |
| Pod Sandbox | gemeinsam genutztes Podnetz | Sandbox-/IP-Erzeugung oder Namespaceverlust |
| Container | Image und Prozess | Start-, Config-, Exit- oder OOM-Fehler |
| Service/Ingress | Erreichbarkeit und Routing | keine Ready Endpoints, falscher Port oder Policy |
| Persistent Volume | Datenpfad | Attach/Mount, Zone, Rechte, Snapshot oder Backend |
Die Phase Running bedeutet, dass mindestens ein primärer Container läuft oder startet; sie ist kein Anwendungs-SLA. Containerstatus, Conditions, Events, Probes und Controllerzustand werden gemeinsam ausgewertet (Kubernetes – Pod Lifecycle).
kubectl get pod $env:POD -n $env:NAMESPACE -o wide
kubectl describe pod $env:POD -n $env:NAMESPACE
kubectl logs $env:POD -n $env:NAMESPACE --all-containers --previous
crictl ps --all
crictl inspectp $env:POD_SANDBOX_ID
kubectl get pod "$POD" -n "$NAMESPACE" -o wide
kubectl describe pod "$POD" -n "$NAMESPACE"
kubectl logs "$POD" -n "$NAMESPACE" --all-containers --previous
crictl ps --all
crictl inspectp "$POD_SANDBOX_ID"
kubectl get, kubectl describe und kubectl logs zeigen API-, Ereignis- und Containerperspektive. crictl untersucht die CRI-Sicht auf dem Node. Ein kubectl exec verändert und beobachtet die Laufzeitinstanz; es ersetzt kein reproduzierbares Image oder Runbook.
Compose und deklarative Einzelhostsysteme
Compose beschreibt Services, Netzwerke, Volumes, Secrets, Configs und Abhängigkeiten in einem Anwendungsmodell. Es ist für Einzelhost- und Entwicklungsabläufe wertvoll, aber weder Registry noch Clusterorchestrator. Die Compose Specification definiert das Modell unabhängig von einer bestimmten CLI (Compose Specification).
Eine produktionsfähige Composeablage enthält:
- Image-Digests oder kontrollierte Tagauflösung und dokumentierte Plattform;
- explizite Mounts, Read-only-Rootfs und schreibbare Pfade;
- Ressourcen-, Restart-, Stop- und Healthsemantik;
- getrennte Konfiguration und Secretreferenzen;
- Netzwerke und veröffentlichte Ports;
- Logging- und Rotationsvorgaben;
- Backup-/Restore- und Updateverfahren ausserhalb der YAML-Datei.
docker compose config rendert die zusammengeführte Konfiguration und zeigt Variablenauflösung. Die Ausgabe kann Secrets enthalten und wird entsprechend behandelt (Docker – docker compose config).
Image Pull, Registry und Cache
Eine Registry verteilt Content über Manifeste und Blobs. Authentisierung, Repositoryautorisierung, Tagauflösung, Mirror, Proxycache und lokale Content Stores können getrennt scheitern. Kubernetes imagePullPolicy entscheidet, wann kubelet die Registry kontaktiert; auch Always verwendet lokal vorhandene Layer, wenn der aufgelöste Digest bereits vorhanden ist (Kubernetes – Images).
Ein produktiver Rollout protokolliert Registry, Repository, Tag, aufgelösten Digest, Plattform, Signatur-/Provenanceentscheidung und Nodebestand. Garbage Collection auf Registry oder Node darf keine noch für Rollback benötigten Digests entfernen. Air-Gapped-Betrieb benötigt zusätzlich Spiegel-, Schlüssel-, Revocation- und Metadatenprozess.
Supply-Chain- und Laufzeitsicherheit
NIST trennt Risiken in Images, Registries, Orchestratoren, Container und Hostbetriebssysteme. Ein Scannergebnis ist nur ein Signal: Paketinventar kann unvollständig sein, eine CVE kann nicht erreichbar oder umgekehrt ein anwendungseigener Fehler unsichtbar sein. Policy verbindet Herkunft, Signatur, bekannte Schwachstellen, Konfiguration und Laufzeitkontext (NIST SP 800-190).
Kubernetes Pod Security Standards definieren die Profile Privileged, Baseline und Restricted. Restricted verlangt unter anderem Non-Root-Ausführung, ein Seccompprofil und stark begrenzte Capabilities; konkrete Workloads müssen dennoch funktional getestet werden (Kubernetes – Pod Security Standards).
Mindestens geprüft werden:
- vertrauenswürdige Registry und unveränderlicher Digest;
- Buildprovenance, Signatur und kontrollierte Schlüssel-/Identitätsquelle;
- minimales Base Image und keine Buildsecrets in Layers;
- Non-Root, Capability-Drop, Seccomp/LSM, Read-only-Rootfs, begrenzte Geräte und Mounts;
- keine Runtime-Sockets oder Hostnamespaces ohne explizite Ausnahme;
- Network Policies beziehungsweise Hostfirewall und kontrollierter Egress;
- Ressourcen- und PIDlimits gegen lokale Erschöpfung;
- Patch-, Rebuild-, Rollout- und Rollbackpfad.
Windows-Container
Windows-Container verwenden Windows-Images und Windows-Kernelmechanismen. Microsoft unterscheidet Process Isolation, bei der Container den Hostkernel teilen, und Hyper-V Isolation, bei der jeder Container in einer optimierten VM mit eigenem Kernel läuft. Beide verwenden dasselbe Imageformat und dieselben Verwaltungswerkzeuge, aber andere Isolations- und Kompatibilitätsgrenzen (Microsoft Learn – Windows and containers, Microsoft Learn – Isolation modes).
Bei Process Isolation müssen Host- und Containerbetriebssystem kompatibel sein. Hyper-V Isolation kann bestimmte Versionsunterschiede entkoppeln, erhöht aber Ressourcen- und Startkosten. Microsoft dokumentiert die unterstützten Host-/Imagekombinationen; «Windows Container» ist daher ohne Base-Image-, Build- und Isolationsangabe unvollständig (Microsoft Learn – Windows container version compatibility).
Linux- und Windows-Nodes teilen nicht denselben Kernel und nicht dieselben Imagebinaries. Multi-OS-Cluster benötigen Schedulinglabels, passende DaemonSets, Netzwerk-/Storageplugins und unterschiedliche Diagnosepfade.
Updates, Rollout und Rollback
Ein Containerupdate ist ein Imagewechsel plus Zustandsübergang. Vor dem Rollout werden Release Notes, Schemaänderungen, Migrationsschritte, Mindestversionen externer Dienste, neue Ports/Scopes und Rückwärtskompatibilität geprüft. Ein Rollback des Images kann nach einer nicht rückwärtskompatiblen Datenmigration unmöglich sein.
Der kontrollierte Ablauf lautet:
- Ziel-Digest, Signatur, Provenance und Scanentscheidung festhalten;
- Backup beziehungsweise getesteten Recoverypunkt der persistenten Daten herstellen;
- Konfigurations- und Schemadiff prüfen;
- Canary oder gestufte Replikas mit realen Probes und SLOs ausrollen;
- Datenmigration und Mixed-Version-Fähigkeit beobachten;
- Digest, Instanzen, Events, Fehler, Latenz und Ressourcen verifizieren;
- Rollback nur innerhalb der nachgewiesenen Datenkompatibilität auslösen.
Dieser Prozess verbindet Releases, Migration und Backup/DR. Automatische Tag-Updater ohne fachliche Gates verschieben den Änderungszeitpunkt lediglich aus dem Changeprozess in einen Bot.
Backup und Disaster Recovery
Ein vollständiger Containerdienst besteht aus mehr als Volumes:
- Deploymentdefinitionen, Policies und Netzwerkobjekten;
- registrierten Image-Digests oder einem wiederherstellbaren Registryspiegel;
- nicht-sensitiver Konfiguration und Secret-/Schlüsselquellen;
- persistenten Daten mit anwendungskonsistentem Verfahren;
- externen Datenbanken, Queues, Objektstores, DNS- und Identitätsabhängigkeiten;
- Schemaversionen, offenen Jobs und Reconciliationzustand;
- Runbooks für Node-, Cluster-, Registry- und Standortverlust.
Ein Tar-Archiv des Volumepfads kann bei laufender Datenbank inkonsistent sein. Storage-Snapshots benötigen Freeze-/Quiesce- oder datenbankspezifische Semantik. Ein Restoretest baut Dienst, Netzwerk und Identitäten auf einer sauberen Zielumgebung neu auf, startet mit dem gesicherten Digest und prüft fachliche Daten sowie offene Queues.
Bei Störungen wird vom Artefakt zum Prozess und dann nach aussen geprüft: Image, Startparameter, Rechte, Mounts, Namensauflösung, Netzwerkpfad und externe Dienste.
Diagnose nach Abhängigkeitsschichten
Ein Containerincident wird von aussen nach innen eingegrenzt:
- Desired State: Welche Definition und welcher Digest sollten laufen?
- Placement: Auf welchem Host/Node, mit welcher Plattform und Kapazität?
- Image: Pull, Auth, Manifest, Plattform, Signatur und lokaler Content?
- Runtime: Sandbox, Containerstatus, Exitcode, OOM, Restart und Events?
- Prozess: PID 1, Signale, Benutzer, Capabilities und offene Dateien?
- Storage: erwarteter Mount, Backend, Rechte, Kapazität und I/O?
- Netzwerk: Namespace, DNS, Route, Policy, Listener, Service und TLS?
- Anwendung: Health, Logs, Queue, Schema, Credential und externe Abhängigkeit?
docker version
docker info
docker context show
docker compose config --images
docker compose ps --all
docker system df
docker version
docker info
docker context show
docker compose config --images
docker compose ps --all
docker system df
uname -a
docker version trennt Client- und Serverversion, docker info zeigt Engine-, Runtime-, Storage- und Securitykontext, docker context show das tatsächlich administrierte Ziel und docker system df lokalen Contentverbrauch. uname belegt im Unix-Beispiel Kernel und Plattform.
Technische Geschichte
Prozessisolation ist älter als moderne Images. Unix chroot änderte die Dateisystemwurzel eines Prozesses, war aber nie als vollständige Sicherheitsgrenze gedacht. FreeBSD Jails erweiterten Ende der 1990er-Jahre beziehungsweise mit FreeBSD 4.0 das Modell um isoliertere Host- und Netzwerkansichten; Solaris Zones verbanden Anwendungsisolation und Ressourcenverwaltung im Betriebssystem (FreeBSD Handbook – Jails, Oracle Solaris Zones Introduction).
Linux führte schrittweise Namespaces und Control Groups ein. LXC kombinierte diese Kernelmechanismen zu Systemcontainern. Docker machte ab 2013 Image-Layers, Registryverteilung, Dockerfiles und eine konsistente Entwickleroberfläche populär; anfänglich verwendete es LXC und wechselte später zu einer eigenen Laufzeitbibliothek (Linux Containers – LXC Introduction, Docker – What is a container?).
2015 gründeten Hersteller und Plattformanbieter die Open Container Initiative, um Runtime- und Imageformate offen zu standardisieren. runc wurde zur OCI-Runtimebasis; containerd und CRI-O etablierten High-Level-Runtimes. Kubernetes abstrahierte Node-Runtimes über CRI, Netzwerke über CNI und Storage über CSI. Heute bildet «Container» deshalb keinen einzelnen Produktstack, sondern eine Kette interoperabler Spezifikationen und Implementierungen (Open Container Initiative – Overview, Kubernetes – Container Runtimes).
Admin-Checkliste auf einen Blick
Der Container ist nur ein Teil des Dienstes. Für die Betriebsfreigabe werden deshalb Artefakt, Laufzeit, Host, Netzwerk, Speicher und Recovery als zusammenhängende Kette geprüft.
| Frage | Betriebsnachweis |
|---|---|
| Welches Artefakt läuft? | Registry, Repository, Tag, Digest, Plattform, Configdigest, Signatur/Provenance |
| Welche Laufzeitkette gilt? | Engine/Orchestrator, CRI, High-Level-Runtime, OCI-Runtime, Hostkernel |
| Welche Isolation ist aktiv? | Namespaces, Windows-Isolationsmodus, UIDmapping, Capabilities, Seccomp, LSM |
| Wo liegt Zustand? | Writable Layer, Volume, Bind Mount, tmpfs und externe Dienste je Datenklasse |
| Was ist erreichbar? | Listenadresse, Container-/Pod-IP, Service, Published Port, Ingress und Egresspolicy |
| Wer besitzt Identität? | Prozess-UID/SID, Service Account, Registrycredential, Workloadtoken und Schlüsselquelle |
| Welche Grenzen gelten? | CPU, Memory, PIDs, I/O, Disk, Logrotation, Quota und Node-Eviction |
| Was bedeutet gesund? | Prozess, Startup, Readiness, Liveness, fachlicher Test und externe Abhängigkeiten getrennt |
| Wie wird geändert? | freigegebener Digest, Schema-/Configdiff, Canary, Mixed Version, Rollbackfenster |
| Wie wird wiederhergestellt? | Definitionen, Registry/Images, Secrets/Keys, Daten, Queues und sauberer Restoretest |
Quellen
- NIST SP 800-190 – Application Container Security Guide
- OCI Image Specification
- OCI Runtime Specification
- OCI Distribution Specification
- OCI Image Manifest
- OCI Image Configuration
- Docker – Storage drivers
- Docker – Multi-stage builds
- SLSA Specification
- Sigstore cosign – Signing containers
- Docker CLI – imagetools inspect
- Docker CLI – image inspect
- Sigstore cosign – Verify
- jq manual
- runc
- containerd
- Kubernetes – Container Runtime Interface
- namespaces(7)
- Docker CLI – container run / init
- Linux kernel – Control Group v2
- Kubernetes – Resource Management
- Docker CLI – container inspect
- Docker CLI – container top
- Docker CLI – stats
- Microsoft Learn – Get-Process
- ps(1)
- capabilities(7)
- Docker – Seccomp security profiles
- Docker – AppArmor security profiles
- user_namespaces(7)
- Docker – Rootless mode
- CNI Specification
- Docker – Container networking
- Docker CLI – network inspect
- Docker CLI – container port
- Microsoft Learn – Get-NetTCPConnection
- ss(8)
- Microsoft Learn – Test-NetConnection
- OpenBSD – nc
- Docker – Storage overview
- Container Storage Interface Specification
- Docker CLI – volume inspect
- Microsoft Learn – Get-Volume
- Microsoft Learn – Get-PSDrive
- findmnt(8)
- GNU coreutils – df
- Kubernetes – Secrets
- Dockerfile reference – HEALTHCHECK
- Kubernetes – Probes
- Docker Compose – Control startup order
- Docker CLI – container logs
- Docker CLI – events
- Docker CLI – compose ps
- systemd – journalctl
- Docker – Configure logging drivers
- Docker – Start containers automatically
- Kubernetes – Pods
- Kubernetes – Deployments
- Kubernetes – Pod Lifecycle
- kubectl get
- kubectl describe
- kubectl logs
- Kubernetes – crictl
- Compose Specification
- Docker CLI – compose config
- Kubernetes – Images
- Kubernetes – Pod Security Standards
- Microsoft Learn – Windows and containers
- Microsoft Learn – Isolation modes
- Microsoft Learn – Windows container version compatibility
- Docker CLI – version
- Docker CLI – info
- Docker CLI – context show
- Docker CLI – system df
- GNU coreutils – uname
- FreeBSD Handbook – Jails
- Oracle Solaris Zones Introduction
- Linux Containers – LXC Introduction
- Docker – What is a container?
- Open Container Initiative – Overview
- Kubernetes – Container Runtimes