Theorie 06 · Laufzeitumgebung
Der Bauplan ist
nicht das Gebäude
Docker macht eine Anwendung reproduzierbar startbar. Es ersetzt aber weder Architektur, Datensicherung noch Betrieb. Dieses Kapitel erklärt Images, Container, Netzwerke, Volumes, Compose und die Sicherheitsgrenzen des TEKO-Labors.
Reproduzierbarkeit durch explizite Bausteine
Eine klassische Installationsanleitung sagt: „Installiere Python, nginx und Orthanc, kopiere Dateien und ändere drei Konfigurationen.“ Das Ergebnis hängt von Betriebssystem, bereits installierten Paketen und manuellen Schritten ab. Docker verpackt Programm und Laufzeitabhängigkeiten in Images. Compose beschreibt, welche Container, Netze, Volumes, Umgebungsvariablen und Healthchecks gemeinsam eine Anwendung bilden.
Das Ziel ist nicht, jeden Unterschied der Umgebung verschwinden zu lassen. Kernel, CPU-Architektur, Speicher, Dateisystem und Docker-Version bleiben relevant. Docker reduziert jedoch viele unkontrollierte Variablen. Ein identischer Commit und ein festgelegtes Image sollen lokal, im Test und auf dem Unterrichtsserver denselben Stack erzeugen.
Unveränderlicher Bauzustand, veränderlicher Laufzustand
Ein Image besteht aus schreibgeschützten Schichten. Ein Tag wie nginx:alpine ist ein beweglicher Name; er kann später auf andere Inhalte zeigen. Für reproduzierbare Releases werden Versions-Tags oder Digests verwendet. Der Build sollte nur notwendige Dateien aufnehmen, einen kleinen vertrauenswürdigen Basisstand verwenden und keine Secrets enthalten.
Beim Start erhält der Container eine beschreibbare Laufzeitschicht. Änderungen dort verschwinden normalerweise, wenn der Container ersetzt wird. Das ist erwünscht: Ein Deployment soll den Container austauschen können, statt ihn manuell „zurechtzureparieren“. Konfiguration kommt aus Dateien, Variablen oder Secrets; persistente Fachdaten gehören in Volumes oder externe Datenbanken.
apk add ein Diagnosewerkzeug und ändert eine Konfiguration. Der Fehler scheint gelöst, aber beim nächsten Neustart ist alles verschwunden. Die Änderung war weder versioniert noch getestet.Im Container bedeutet localhost „ich selbst“
Compose legt ein privates Netzwerk an. Dienste erreichen einander über ihren Servicenamen, beispielsweise http://orthanc:8042. localhost im API-Container bezeichnet dagegen den API-Container selbst, nicht Orthanc und nicht den Host. Dieses Denkmodell erklärt viele vermeintliche Netzwerkfehler.
expose dokumentiert interne Ports, veröffentlicht sie aber nicht ins Hostnetz. ports erstellt eine Hostweiterleitung. Für das TEKO-Labor wird nur das Web-Gateway auf 127.0.0.1:3190 gebunden. Die Host-nginx-Instanz veröffentlicht die Domain mit TLS. Orthanc und die Lern-API haben keine Hostports. Dadurch sind sie nur über die bewusst definierten Gateway-Routen erreichbar.
| Adresse | Aus Sicht von | Bedeutung |
|---|---|---|
localhost:8042 | Orthanc-Container | Orthanc selbst |
orthanc:8042 | Spital-API im Compose-Netz | Orthanc per Service-DNS |
127.0.0.1:3190 | VM-Host | Gateway, nur lokal gebunden |
teko.algorithma.app | Internet | TLS-Reverse-Proxy zum Gateway |
Ein Container-Port ist kein Sicherheitsmechanismus an sich. Sobald ein Port auf 0.0.0.0 veröffentlicht wird, kann Docker den Verkehr auf manchen Hosts an der erwarteten Host-Firewall vorbei routen. Deshalb werden Bind-Adresse, Firewall und Reverse Proxy gemeinsam geprüft.
Volumes speichern – und müssen trotzdem gesichert werden
Ein benanntes Volume überlebt den Austausch eines Containers. Orthanc kann darin seinen Index und die synthetischen DICOM-Objekte speichern; die Lern-API kann Jobzustände behalten. Das Volume ist aber kein Backup. Ein versehentliches docker compose down -v, ein Dateisystemschaden oder eine falsche Anwendung kann Daten weiterhin löschen oder beschädigen.
Persistenz beantwortet „bleiben die Daten beim Neustart?“. Backup beantwortet „können wir einen früheren, konsistenten Zustand wiederherstellen?“. Für ein öffentliches Demo-Labor ist ein Reset erwünscht und Daten sind synthetisch. Für ein reales PACS wäre eine getestete Sicherungs- und Wiederherstellungsstrategie unverzichtbar.
Ein überprüfbarer Vertrag für die Laufzeit
Compose beschreibt Services, Images oder Builds, Netzwerke, Volumes, Healthchecks, Abhängigkeiten und Sicherheitsoptionen. docker compose config löst Variablen und Zusammenführungen auf und zeigt die effektive Konfiguration. Dieser Schritt gehört vor jeden Start, weil YAML-Einrückung oder fehlende Variablen sonst erst zur Laufzeit auffallen.
services:
course-web:
build: .
ports:
- "127.0.0.1:3190:80"
depends_on:
spital-api:
condition: service_healthy
spital-api:
build: ./lab
environment:
ORTHANC_URL: http://orthanc:8042
expose: ["8080"]
orthanc:
image: jodogne/orthanc:1.12.11
expose: ["8042"]
depends_on allein beweist nicht, dass ein Dienst fachlich bereit ist. Ein Healthcheck sollte eine relevante, günstige Operation prüfen. Der Webdienst kann „Prozess läuft“ melden, während seine Datenbank unerreichbar ist. Das Labor trennt deshalb Liveness und Readiness: Der Prozess kann leben, aber für Jobs noch nicht bereit sein.
Container sind eine Grenze – aber keine Ausrede
Ein Container sollte mit möglichst wenig Rechten laufen. Dazu gehören ein Nicht-root-Benutzer, read_only für unveränderliche Dateisysteme, no-new-privileges, entfernte Linux-Capabilities, begrenzte Prozesse und Ressourcen sowie nur notwendige schreibbare tmpfs- oder Volume-Pfade. Images werden aktualisiert und ihre Herkunft dokumentiert.
Secrets gehören weder in das Image noch in eine öffentlich erreichbare Datei. Eine Compose-Variable kann in Prozess- und Inspektionsdaten sichtbar sein; für produktive Geheimnisse sind Docker Secrets oder ein externer Secret Store geeigneter. Im TEKO-Stack kennt nur die interne Lern-API die Orthanc-Zugangsdaten. Der Browser erhält sie nie.
- Keine Adminoberfläche anonym ins Internet stellen.
- Keine Builddateien,
.env, Git-Daten oder Compose-Dateien in den Webroot kopieren. - Nur das Gateway veröffentlichen; interne Services bleiben im privaten Netz.
- Request-Größe, Rate und Eingabewerte begrenzen.
- Containerlogs rotieren, damit ein Fehler nicht die Platte füllt.
- Images und Konfiguration versionieren; Rollback vor dem Deployment planen.
Starten ist erst der Anfang
Ein guter Laborablauf ist reproduzierbar: Versionen prüfen, Konfiguration rendern, Images bauen, Dienste mit Healthchecks starten, Status ansehen, API-Smoke-Test ausführen, Logs prüfen und anschließend kontrolliert stoppen. Bei Fehlern wird zuerst beobachtet, nicht blind neu gestartet.
- Validieren
docker compose config --quietund benötigte Variablen prüfen. - BauenVersionierte Images erstellen; Buildfehler nicht durch manuelle Containeränderungen umgehen.
- Starten
docker compose up -d --waitund Exitcode beachten. - BeweisenHealth-, Contract- und Happy-Path-Tests ausführen.
- StörenEinen Dienst bewusst stoppen und Retry/Recovery beobachten.
- Aufräumen
downerhält Volumes;down -vist der explizite destruktive Reset.
Kontrollfragen
- Warum darf nur
course-webeinen Hostport besitzen? - Was verliert man beim Container-Ersatz, was beim Volume-Löschen?
- Warum ist
latestfür ein reproduzierbares Release problematisch? - Welche Aussage kann ein Healthcheck nicht automatisch beweisen?
- Warum ist ein laufender Container noch kein getestetes Deployment?
Die Seite Docker-Labor aufsetzen, testen und zurücksetzen enthält alle Befehle mit erwarteten Ergebnissen für lokal und öffentlich.