TEKO Schweizerische FachschuleEAI IntegrationslaborTheorie 6 · Docker & Compose
Docker-Anleitung

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.

ca. 13 MinutenImageContainerNetzwerkVolumeCompose
1 · Grundmodell

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.

Docker-Bauplan und laufende ContainerLinks stehen Dockerfile und Compose als Baupläne, in der Mitte unveränderliche Images und rechts laufende Container mit Netzwerk und Volumes.DockerfileBauplan eines Imagescompose.yamlOrchester der DiensteImagesversionierte Schichtenweb · api · orthanccourse-webspital-apiorthanc
Dockerfile und Compose sind Deklarationen. Erst ein gestarteter Container besitzt einen Prozesszustand. Persistente Daten liegen bewusst außerhalb der flüchtigen Containerschicht.
Metapher: Rezept, Tiefkühlgericht und KücheDas Dockerfile ist das Rezept, das Image ein reproduzierbares Paket und der Container die laufende Zubereitung. Compose koordiniert mehrere Stationen.
Wo die Metapher endetContainer teilen den Kernel des Hosts, sind Prozesse mit Isolation und keine vollständigen virtuellen Maschinen. Ein Image ist auch nicht automatisch sicher oder aktuell.
2 · Image & Container

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.

Gegenbeispiel: Jemand installiert im laufenden Container mit 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.
Entscheidungsregel: Alles, was für den nächsten Start nötig ist, muss im Image, in versionierter Konfiguration oder in einem bewusst verwalteten Datenspeicher stehen – nicht nur in der Laufzeitschicht eines Containers.
3 · Netzwerke

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.

AdresseAus Sicht vonBedeutung
localhost:8042Orthanc-ContainerOrthanc selbst
orthanc:8042Spital-API im Compose-NetzOrthanc per Service-DNS
127.0.0.1:3190VM-HostGateway, nur lokal gebunden
teko.algorithma.appInternetTLS-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.

4 · Persistenz

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.

Bind Mount vs. Volume: Ein Bind Mount zeigt einen konkreten Hostpfad in den Container und eignet sich beispielsweise für versionierte Konfiguration. Ein Docker-Volume wird von Docker verwaltet und eignet sich für Laufzeitdaten. Die Wahl ändert nichts daran, dass Eigentümer, Kapazität und Backup festgelegt werden müssen.
5 · Compose

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.

6 · Härtung

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.
7 · Betrieb

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.

  1. Validierendocker compose config --quiet und benötigte Variablen prüfen.
  2. BauenVersionierte Images erstellen; Buildfehler nicht durch manuelle Containeränderungen umgehen.
  3. Startendocker compose up -d --wait und Exitcode beachten.
  4. BeweisenHealth-, Contract- und Happy-Path-Tests ausführen.
  5. StörenEinen Dienst bewusst stoppen und Retry/Recovery beobachten.
  6. Aufräumendown erhält Volumes; down -v ist der explizite destruktive Reset.

Kontrollfragen

  1. Warum darf nur course-web einen Hostport besitzen?
  2. Was verliert man beim Container-Ersatz, was beim Volume-Löschen?
  3. Warum ist latest für ein reproduzierbares Release problematisch?
  4. Welche Aussage kann ein Healthcheck nicht automatisch beweisen?
  5. Warum ist ein laufender Container noch kein getestetes Deployment?
Schritt für Schritt ausführen
Die Seite Docker-Labor aufsetzen, testen und zurücksetzen enthält alle Befehle mit erwarteten Ergebnissen für lokal und öffentlich.