Das Union Filesystem hinter jedem Docker Container
Wer täglich Docker Container startet, nutzt OverlayFS meist ohne es zu wissen. Wer versteht, wie lowerdir, upperdir und workdir zusammenspielen und wann der teure Copy up Mechanismus greift, kann Image Layer bewusster gestalten und Performance Probleme bei großen Dateien in Containern gezielt vermeiden.
Inhaltsverzeichnis
- 1. Warum jeder Container auf einem Union Filesystem steht
- 2. Das Konzept: lowerdir, upperdir und workdir
- 3. Wie Docker Image Layer darauf aufbaut
- 4. OverlayFS manuell mounten und testen
- 5. Der Copy up Mechanismus und seine Kosten
- 6. Mehrschichtige lowerdir Stacks im Detail
- 7. Performance Charakteristik im Vergleich zum nativen Dateisystem
- 8. Best Practices für den Betrieb von Container Hosts
- 9. Typische Stolperfallen im produktiven Betrieb
- 10. Zusammenfassung
- 11. FAQ
1. Warum jeder Container auf einem Union Filesystem steht
Ein Docker Image besteht aus mehreren übereinander gestapelten, schreibgeschützten Layern, und jeder laufende Container bekommt zusätzlich eine eigene, beschreibbare Schicht obenauf. Damit das für Anwendungen im Container wie ein ganz normales, einheitliches Dateisystem aussieht, kommt ein Union Filesystem zum Einsatz, das mehrere Verzeichnisbäume transparent zu einer einzigen Sicht zusammenführt.
OverlayFS ist seit Kernel 3.18 fester Bestandteil des Linux Kernels und hat sich als Standard Storage Driver für Docker und containerd durchgesetzt, weil es im Vergleich zu älteren Ansätzen wie AUFS deutlich einfacher implementiert ist und direkt im Mainline Kernel gepflegt wird. Wer versteht, wie OverlayFS intern funktioniert, versteht damit gleichzeitig, warum Container so schnell starten und warum bestimmte Workloads in Containern überraschend langsam sein können.
2. Das Konzept: lowerdir, upperdir und workdir
OverlayFS kombiniert mindestens zwei Verzeichnisse zu einer einzigen Sicht: lowerdir enthält eine oder mehrere schreibgeschützte Schichten, während upperdir die einzige beschreibbare Schicht darstellt, in die alle Änderungen tatsächlich geschrieben werden. Aus Sicht eines Prozesses, der den kombinierten Mount Punkt betritt, existiert nur ein einziger, zusammengeführter Dateibaum, in dem Dateien aus oberen Schichten gleichnamige Dateien aus unteren Schichten verdecken.
Das dritte notwendige Verzeichnis, workdir, ist rein internes Arbeitsverzeichnis des Kernels für atomare Operationen wie das Umbenennen von Dateien und darf niemals manuell beschrieben oder anderweitig genutzt werden. Es muss auf demselben Dateisystem wie upperdir liegen, weil OverlayFS für bestimmte Operationen intern auf Rename Systemaufrufe angewiesen ist, die nur innerhalb desselben Dateisystems atomar funktionieren.
# Verzeichnisstruktur für einen manuellen OverlayFS Mount vorbereiten
mkdir -p /overlay/lower /overlay/upper /overlay/work /overlay/merged
# OverlayFS mit einer einzelnen lower Schicht mounten
mount -t overlay overlay \
-o lowerdir=/overlay/lower,upperdir=/overlay/upper,workdir=/overlay/work \
/overlay/merged
3. Wie Docker Image Layer darauf aufbaut
Jede Anweisung in einem Dockerfile, die den Dateisystemzustand verändert, erzeugt in der Regel einen eigenen, schreibgeschützten Layer, der als eigenes Verzeichnis im Storage Backend abgelegt wird. Beim Starten eines Containers stapelt Docker sämtliche Layer eines Images als lowerdir Kette übereinander, wobei die Reihenfolge der Layer über deren Erstellungszeitpunkt und Abhängigkeitskette bestimmt wird, und legt eine neue, leere Schicht als upperdir für den Container selbst an.
Der Storage Driver overlay2 unterstützt seit Kernel 4.0 mehrere lowerdir Einträge gleichzeitig, was die frühere Beschränkung auf zwei Ebenen im ursprünglichen OverlayFS Design überflüssig macht und erklärt, warum moderne Docker Installationen Images mit vielen Layern ohne merkbaren Performance Verlust handhaben können.
# Layer eines laufenden Containers auf Host Ebene inspizieren
docker inspect --format '{{ .GraphDriver.Data.LowerDir }}' meincontainer
docker inspect --format '{{ .GraphDriver.Data.UpperDir }}' meincontainer
# Storage Driver und Backing Filesystem des Docker Daemons pruefen
docker info --format '{{ .Driver }}'
4. OverlayFS manuell mounten und testen
Für Fehlersuche und zum Verständnis lohnt sich ein manueller Mount außerhalb von Docker, weil sich damit isoliert nachvollziehen lässt, welche Datei aus welcher Schicht im zusammengeführten Verzeichnis sichtbar ist. Änderungen, die im gemergten Verzeichnis vorgenommen werden, landen ausschließlich in upperdir, während lowerdir davon vollständig unberührt bleibt, selbst wenn eine Datei dort scheinbar überschrieben wurde.
Wird eine Datei aus einer unteren Schicht im gemergten Verzeichnis gelöscht, legt OverlayFS in upperdir eine sogenannte Whiteout Datei an, ein spezielles Character Device mit den Major und Minor Nummern 0, das dem Kernel signalisiert, die gleichnamige Datei aus den unteren Schichten beim Zusammenführen der Sicht zu ignorieren, ohne dass die Originaldatei in der unteren Schicht tatsächlich gelöscht wird.
# Beispiel: Datei nur in der unteren Schicht anlegen
echo "original" > /overlay/lower/config.txt
# Im gemergten Verzeichnis löschen und Whiteout Datei inspizieren
rm /overlay/merged/config.txt
ls -la /overlay/upper/config.txt
stat /overlay/upper/config.txt | grep 'character special'
5. Der Copy up Mechanismus und seine Kosten
Sobald eine Datei, die nur in einer unteren Schicht existiert, im gemergten Verzeichnis verändert werden soll, kopiert der Kernel sie zunächst vollständig in upperdir, bevor die eigentliche Schreiboperation ausgeführt wird. Dieser Vorgang heißt Copy up und ist bei kleinen Konfigurationsdateien kaum spürbar, wird bei großen Dateien wie Datenbankdateien oder Log Archiven im mehrstelligen Megabyte oder Gigabyte Bereich aber zu einer echten Latenzquelle, weil selbst das Ändern eines einzelnen Bytes die vollständige Datei kopiert.
Für Workloads, die häufig große Dateien innerhalb eines Containers verändern, etwa eine Datenbank, die direkt im Container Dateisystem statt in einem gemounteten Volume läuft, führt genau dieser Effekt zu unerwarteten Latenzspitzen beim ersten Schreibzugriff nach dem Containerstart. Die Standardempfehlung lautet deshalb, veränderliche und schreibintensive Daten grundsätzlich über Bind Mounts oder benannte Volumes außerhalb des OverlayFS Layer Stacks zu führen.
6. Mehrschichtige lowerdir Stacks im Detail
Bei mehreren lowerdir Einträgen werden diese durch Doppelpunkt getrennt angegeben, wobei die Reihenfolge entscheidend ist: Der erste angegebene Pfad hat die höchste Priorität und verdeckt gleichnamige Dateien aus allen folgenden Pfaden. Docker nutzt diese Eigenschaft, um Layer in der richtigen historischen Reihenfolge zu stapeln, sodass ein später im Dockerfile erzeugter Layer stets Vorrang vor einem früheren Layer hat.
Für tiefe Layer Stacks mit vielen Ebenen, wie sie bei Images mit dutzenden Dockerfile Anweisungen entstehen, steigt die Anzahl der Lookups beim Öffnen einer Datei linear mit der Anzahl der Schichten, weil der Kernel im schlimmsten Fall jede Schicht von oben nach unten durchsuchen muss, bis die Datei gefunden wird. In der Praxis bleibt dieser Effekt bei üblichen Image Größen vernachlässigbar, kann bei extrem vielen Layern aber messbar werden.
# Mehrere lower Schichten kombinieren, erste hat hoechste Prioritaet
mount -t overlay overlay \
-o lowerdir=/overlay/layer3:/overlay/layer2:/overlay/layer1,\
upperdir=/overlay/upper,workdir=/overlay/work \
/overlay/merged
7. Performance Charakteristik im Vergleich zum nativen Dateisystem
Lesezugriffe auf Dateien, die bereits in upperdir liegen oder unverändert aus der obersten passenden lowerdir Schicht gelesen werden, sind nahezu so schnell wie direkte Zugriffe auf das darunterliegende native Dateisystem, weil OverlayFS dafür keine zusätzliche Kopieroperation benötigt. Der spürbare Overhead entsteht fast ausschließlich beim erwähnten Copy up sowie bei Metadaten Operationen über viele Schichten hinweg.
Für Datenbank Workloads mit vielen kleinen, zufällig verteilten Schreibzugriffen empfiehlt sich grundsätzlich ein Bind Mount oder Volume statt des OverlayFS Layer Stacks, weil dort weder Copy up noch Whiteout Verwaltung anfallen und die I/O Pfade direkt auf das native Dateisystem des Hosts durchgereicht werden.
8. Best Practices für den Betrieb von Container Hosts
Auf dem Host lohnt sich ein regelmäßiges docker system prune oder das Äquivalent des jeweiligen Container Runtimes, weil ungenutzte Layer sonst dauerhaft Speicherplatz im Storage Backend belegen, selbst wenn kein Container mehr darauf verweist. Für produktive Hosts empfiehlt sich außerdem ein eigenes, dediziertes Dateisystem für das Docker Storage Verzeichnis, damit ein vollgelaufener Layer Stack nicht das gesamte Root Dateisystem und damit den Systembetrieb gefährdet.
Images sollten bewusst schlank gehalten werden, etwa durch Multi Stage Builds, die Build Abhängigkeiten in einem verworfenen Zwischen Layer belassen und nur die tatsächlich benötigten Artefakte in den finalen Layer Stack übernehmen. Weniger und kleinere Layer bedeuten weniger Lookups beim Dateizugriff und ein insgesamt schnelleres Starten neuer Container, was besonders bei häufigen Deployments spürbar wird.
9. Typische Stolperfallen im produktiven Betrieb
Die häufigste Falle ist das Speichern veränderlicher Anwendungsdaten direkt im Container Dateisystem statt in einem Volume, was nicht nur die erwähnten Copy up Latenzen verursacht, sondern auch dazu führt, dass alle Daten beim Entfernen des Containers unwiederbringlich verloren gehen, weil upperdir gemeinsam mit dem Container gelöscht wird.
Eine zweite Falle betrifft Dateisystemlimits: Da OverlayFS für jede geänderte Datei potenziell eine vollständige Kopie in upperdir anlegt, kann ein Container, der viele große Dateien verändert, unerwartet schnell die Inode oder Speicherplatzlimits des Host Dateisystems erreichen, selbst wenn das Docker Image selbst vergleichsweise klein wirkt. Auch das Verschachteln von OverlayFS auf OverlayFS, etwa in bestimmten Docker in Docker Szenarien, führt je nach Kernel Version zu Kompatibilitätsproblemen und sollte vermieden werden.
| Verzeichnis | Rolle | Beschreibbar | Besonderheit |
|---|---|---|---|
| lowerdir | Eine oder mehrere schreibgeschützte Basisschichten | Nein | Mehrere Pfade mit Doppelpunkt getrennt, Reihenfolge zählt |
| upperdir | Einzige beschreibbare Schicht | Ja | Enthält Whiteout Dateien für gelöschte untere Einträge |
| workdir | Internes Arbeitsverzeichnis des Kernels | Nur intern | Muss auf demselben Dateisystem wie upperdir liegen |
| merged | Zusammengeführte, sichtbare Gesamtsicht | Ja, über upperdir | Einziger Mount Punkt, den Anwendungen sehen |
Mironsoft
Server-Administration, Docker-Hosts und Performance-Tuning
Linux-Server, die niemand im Team richtig versteht?
Wir übernehmen Setup, Absicherung und Performance-Tuning von Linux-Servern und Docker-Hosts für Magento-Deployments, dokumentiert und nachvollziehbar statt gewachsen und unklar.
Server-Audit
Bestehende Server-Konfiguration auf Sicherheitslücken und Performance-Bremsen prüfen.
Docker-Host-Setup
Produktionsreife Docker-Umgebungen für Magento sauber aufsetzen und absichern.
Monitoring & Tuning
Ressourcenverbrauch messen und Systemd, Kernel und Dienste gezielt optimieren.
10. Zusammenfassung
OverlayFS
Kernkonzept
lowerdir, upperdir und workdir werden zu einer einzigen Sicht kombiniert
Docker Bezug
Jeder Image Layer ist eine lowerdir Schicht, Container Layer ist upperdir
Größte Kostenquelle
Copy up kopiert bei jeder ersten Änderung die gesamte Datei
Best Practice
Veränderliche große Daten über Volumes statt im Layer Stack führen