Rotation, Speicherverbrauch und Integration im Vergleich
Die Standardeinstellung von Docker ist selten die richtige Wahl für produktive Umgebungen. Der Log-Driver json-file rotiert Logs erst nach expliziter Konfiguration und liegt als reine Textdatei vor, während journald Logs direkt in die systemd-Journal-Infrastruktur integriert, mit strukturierten Metadaten und zentraler Abfrage über journalctl.
Inhaltsverzeichnis
- 1. Warum die Wahl des Log-Drivers überhaupt relevant ist
- 2. Der Log-Driver json-file im Detail
- 3. Der Log-Driver journald im Detail
- 4. Rotation und Speicherverbrauch konfigurieren
- 5. Performance-Unterschiede unter Last
- 6. Integration mit zentralem Logging und journalctl
- 7. Log-Driver umstellen: Vorgehen und Fallstricke
- 8. Typische Fehler bei der Log-Driver-Wahl
- 9. json-file und journald im direkten Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum die Wahl des Log-Drivers überhaupt relevant ist
Jeder Docker-Container schreibt seine Ausgaben nach Stdout und Stderr, aber was mit diesen Daten passiert, entscheidet der konfigurierte Log-Driver. Ohne bewusste Konfiguration nutzt Docker standardmäßig json-file, das jede Zeile als JSON-Objekt in eine lokale Datei schreibt, ursprünglich ohne jede Rotation. Auf einem produktiven Host mit langlebigen Containern und geschwätzigen Anwendungen führt das unbemerkt zu Log-Dateien, die die Festplatte füllen, bis der gesamte Host handlungsunfähig wird.
Die Alternative journald bindet Container-Logs stattdessen in das systemd-Journal ein, dieselbe Infrastruktur, die auch für System- und Service-Logs auf modernen Linux-Distributionen verwendet wird. Die Wahl zwischen diesen beiden Log-Driver-Optionen ist keine reine Geschmacksfrage, sondern hat direkte Auswirkungen auf Speicherverbrauch, Performance unter Last und die Integrationsmöglichkeiten mit zentralem Logging. Die folgenden Abschnitte zeigen die konkreten Unterschiede und wann welcher Log-Driver die bessere Wahl ist.
Neben json-file und journald bietet Docker weitere Log-Driver wie syslog, gelf oder fluentd, die Logs direkt an ein externes System weiterreichen, ohne lokale Zwischenspeicherung. Diese Treiber sind für dieses Thema bewusst außen vor gelassen, weil sie eine andere Kategorie von Entscheidung darstellen: Sie ersetzen lokale Speicherung vollständig durch sofortigen Versand, während json-file und journald beide zunächst lokal speichern und erst nachgelagert von einem Collector abgeholt werden. Genau dieser lokale Speicherpfad, mit seinen Konsequenzen für Festplattenverbrauch und Diagnosefähigkeit direkt auf dem Host, macht den Unterschied zwischen den beiden hier verglichenen Log-Driver-Optionen so praxisrelevant.
2. Der Log-Driver json-file im Detail
Der Log-Driver json-file schreibt jede Log-Zeile als eigenständiges JSON-Objekt mit den Feldern log, stream und time in eine Datei unter /var/lib/docker/containers/<container-id>/<container-id>-json.log. Dieses Format ist einfach zu parsen, weshalb es die Grundlage für Tools wie Promtail und Filebeat bildet, die genau dieses JSON-Format standardmäßig erwarten. Der große Vorteil: json-file funktioniert überall, unabhängig vom Betriebssystem, unabhängig davon, ob systemd überhaupt vorhanden ist.
Der entscheidende Nachteil ohne explizite Konfiguration ist die fehlende automatische Rotation in älteren Docker-Versionen und die Notwendigkeit, Limits selbst zu setzen. Ohne max-size und max-file als Log-Optionen wächst die Log-Datei unbegrenzt, solange der Container läuft. Für geschwätzige Anwendungen, etwa einen Webserver mit Access-Logs auf Stdout, kann eine einzelne Log-Datei innerhalb weniger Tage mehrere Gigabyte erreichen und im schlimmsten Fall die verfügbare Festplattenkapazität des gesamten Hosts erschöpfen.
# docker-compose.yml — json-file with explicit rotation limits
services:
web:
image: nginx:1.27
logging:
driver: "json-file"
options:
max-size: "10m" # rotate after 10 MB per file
max-file: "5" # keep at most 5 rotated files (50 MB total)
compress: "true" # gzip rotated files to save disk space
# Inspect the raw log format directly on disk
# cat /var/lib/docker/containers/<id>/<id>-json.log | head -1
# {"log":"GET /health 200\n","stream":"stdout","time":"2026-07-30T10:15:03.421Z"}
# Set json-file with limits as the daemon-wide default
# /etc/docker/daemon.json
# {
# "log-driver": "json-file",
# "log-opts": { "max-size": "10m", "max-file": "5" }
# }
Ein weiterer Punkt bei json-file: Da jede Log-Zeile individuell als JSON kodiert wird, verdoppelt sich der tatsächliche Speicherbedarf gegenüber reinem Klartext grob durch die zusätzlichen JSON-Strukturzeichen und Escape-Sequenzen, besonders bei Logs mit vielen Sonderzeichen oder eingebetteten Anführungszeichen. Bei der Kapazitätsplanung für Log-Speicher sollte dieser Overhead von grob 20 bis 30 Prozent gegenüber reinem Text mit eingeplant werden, damit die gewählten max-size-Werte realistisch zur tatsächlich verfügbaren Festplattenkapazität passen.
3. Der Log-Driver journald im Detail
Der Log-Driver journald sendet Container-Logs stattdessen an den systemd-Journal-Daemon, der sie zusammen mit allen anderen System- und Service-Logs in einer binären, indizierten Datenbank speichert. Statt einer separaten Datei pro Container landen alle Logs in derselben zentralen Journal-Struktur, versehen mit zusätzlichen Metadaten wie Container-Name, Image und Container-ID als durchsuchbare Journal-Felder.
Der praktische Vorteil: Die Rotation, Komprimierung und Größenbegrenzung des Journals wird zentral über /etc/systemd/journald.conf für den gesamten Host gesteuert, statt für jeden Container einzeln konfiguriert werden zu müssen. Zusätzlich lassen sich Container-Logs über journalctl mit denselben mächtigen Filtermöglichkeiten durchsuchen, die Administratoren bereits von System-Logs kennen, etwa Zeitbereiche, Prioritätsstufen oder Feld-basierte Filter, ohne ein separates Werkzeug zu benötigen.
# docker-compose.yml — journald as the log driver
services:
web:
image: nginx:1.27
logging:
driver: "journald"
options:
tag: "{{.Name}}" # custom SYSLOG_IDENTIFIER for easier filtering
# Query container logs directly via journalctl
# journalctl CONTAINER_NAME=web -f
# journalctl CONTAINER_NAME=web --since "1 hour ago" -p err
# Set journald as the daemon-wide default
# /etc/docker/daemon.json
# {
# "log-driver": "journald"
# }
Beide Log-Driver unterstützen zusätzlich das Feld labels beziehungsweise tag, um Container-Metadaten in die Log-Ausgabe einzubetten, was besonders bei der späteren Auswertung durch externe Collector hilfreich ist. Bei json-file lassen sich über log-opts zusätzliche Docker-Labels als Felder in jede JSON-Zeile einbetten, bei journald übernimmt der tag-Parameter eine ähnliche Rolle für den SYSLOG_IDENTIFIER. Diese Metadaten-Anreicherung ist unabhängig von der eigentlichen Rotations- und Speicherfrage, spielt aber bei der späteren Filterung in beiden Welten eine wichtige Rolle.
4. Rotation und Speicherverbrauch konfigurieren
Bei json-file liegt die Verantwortung für Rotation vollständig beim Administrator. Die Optionen max-size und max-file begrenzen zusammen die maximale Größe pro Container: Bei max-size: 10m und max-file: 5 entstehen maximal 50 Megabyte Logs pro Container, bevor die älteste Datei überschrieben wird. Diese Limits gelten pro Container und müssen entweder pro Service in der Compose-Datei oder global über daemon.json gesetzt werden, wobei die Container-spezifische Einstellung die globale überschreibt.
Bei journald erfolgt die Größenbegrenzung zentral über SystemMaxUse und RuntimeMaxUse in journald.conf, unabhängig von der Anzahl der Container. Das vereinfacht die Verwaltung erheblich, weil ein einziger Wert die Gesamtgröße des Journals für alle Logs, nicht nur Container-Logs, begrenzt. Der Nachteil dieser zentralen Begrenzung: Ein einzelner sehr geschwätziger Container kann bei knapper Journal-Größe ältere Logs anderer, wichtigerer Services aus dem Journal verdrängen, wenn keine Priorisierung eingerichtet ist.
Ein weiterer praktischer Unterschied betrifft die Behandlung von sehr langen, ungebrochenen Ausgaben ohne Zeilenumbruch. Bei json-file puffert Docker solche Ausgaben bis zu einer internen Obergrenze, bevor sie als eigene Zeile geschrieben werden, was bei Anwendungen mit exotischem Ausgabeverhalten gelegentlich zu unerwartet aufgeteilten Log-Einträgen führen kann. journald verhält sich hier leicht anders, weil die Journal-API eigene Regeln für die maximale Feldgröße mitbringt, sodass extrem lange Einzeleinträge unter Umständen gekürzt oder anders zerlegt werden als bei json-file. Für die überwiegende Mehrheit strukturierter Anwendungs-Logs mit normalen Zeilenlängen spielt dieser Unterschied in der Praxis keine Rolle, verdient aber Aufmerksamkeit bei Anwendungen, die sehr große Stack-Traces oder Binärdaten auf Stdout ausgeben.
5. Performance-Unterschiede unter Last
Unter hoher Log-Last zeigen sich messbare Unterschiede zwischen den beiden Log-Driver-Optionen. json-file schreibt synchron auf die Festplatte, was bei sehr hohem Log-Volumen zu spürbarem I/O-Druck führen kann, besonders auf Hosts mit langsameren Festplatten oder vielen parallel loggenden Containern. Da jede Zeile individuell als JSON serialisiert wird, entsteht zusätzlich ein gewisser CPU-Overhead pro Zeile, der bei geringem Log-Volumen vernachlässigbar, bei extremem Durchsatz aber messbar ist.
journald puffert Schreibvorgänge intern und kann so kurzzeitige Lastspitzen besser abfedern, verursacht aber durch die zusätzliche Indizierung für die Journal-Datenbank ebenfalls Overhead, der sich bei sehr hohen Log-Raten bemerkbar macht. Für die überwiegende Mehrheit produktiver Docker-Umgebungen mit normalem Anwendungs-Logging sind diese Performance-Unterschiede nicht spürbar, erst bei extrem hohem Log-Volumen, etwa mehreren Tausend Zeilen pro Sekunde pro Container, wird die Wahl des Log-Drivers zum messbaren Performance-Faktor.
In der Praxis lohnt sich vor einer endgültigen Entscheidung ein kurzer Lasttest auf einem repräsentativen Staging-Host: Ein Skript, das für einige Minuten mehrere Tausend Log-Zeilen pro Sekunde über mehrere Container gleichzeitig erzeugt, zeigt zuverlässiger als jede theoretische Betrachtung, ob der gewählte Log-Driver unter der erwarteten Produktionslast spürbar CPU oder I/O-Wartezeiten verursacht. Solche Tests decken auch auf, ob die konfigurierten Rotations-Limits im Ernstfall tatsächlich greifen, bevor die Festplatte an ihre Grenzen stößt.
6. Integration mit zentralem Logging und journalctl
Für Teams, die bereits Promtail, Filebeat oder Fluentd einsetzen, ist json-file häufig die einfachere Wahl, weil diese Tools standardmäßig für das JSON-Zeilenformat unter /var/lib/docker/containers konfiguriert sind und ohne zusätzliche Anpassung funktionieren. Wird stattdessen journald verwendet, benötigen diese Collector entweder ein spezielles Journal-Input-Plugin, etwa Promtails journal-Scrape-Konfiguration, oder einen zusätzlichen Export-Schritt.
Umgekehrt profitieren Teams, die bereits eine systemd-zentrierte Infrastruktur betreiben und journalctl für System-Logs im täglichen Einsatz haben, deutlich von journald als Log-Driver, weil Container-Logs dann ohne Kontextwechsel in derselben Oberfläche neben System-Logs erscheinen. Diese Entscheidung hängt also weniger von einer technischen Überlegenheit ab als vielmehr davon, welche Logging-Infrastruktur im jeweiligen Team bereits etabliert ist und welche Tools angebunden werden sollen.
Für Teams, die beide Welten kombinieren möchten, existiert ein pragmatischer Zwischenweg: journald als primärer Log-Driver für die systemd-Integration, ergänzt durch einen periodischen Export ausgewählter Container-Logs in ein JSON-basiertes Archiv für die Weiterverarbeitung durch bestehende Collector. Dieser Ansatz erfordert zusätzlichen Betriebsaufwand, kann aber sinnvoll sein, wenn eine Migration in einem Schritt zu riskant erscheint und beide Zugriffswege parallel für eine Übergangszeit benötigt werden.
7. Log-Driver umstellen: Vorgehen und Fallstricke
Der Log-Driver eines laufenden Containers lässt sich nicht nachträglich ändern, er wird beim Erstellen des Containers festgelegt. Eine Umstellung erfordert deshalb, den Container mit der neuen Konfiguration neu zu erstellen, etwa über docker compose up -d --force-recreate, nachdem die logging-Sektion angepasst wurde. Bereits vorhandene Logs im alten Format bleiben davon unberührt und müssen gegebenenfalls separat archiviert werden, bevor der Container neu erstellt wird und die alte Log-Datei aus dem Blickfeld verschwindet.
Ein häufiger Stolperstein bei der Umstellung auf journald: Der Befehl docker logs funktioniert weiterhin, liest die Daten aber intern über das Journal, was in seltenen Fällen zu leicht abweichendem Zeilenverhalten bei sehr langen, ungebrochenen Log-Ausgaben führen kann. Vor einer flächendeckenden Umstellung des Log-Drivers auf allen Hosts empfiehlt sich ein Testlauf mit wenigen, weniger kritischen Services, um diese Detailunterschiede zu erkennen, bevor produktionskritische Container betroffen sind.
Ein weiterer Aspekt der Umstellung betrifft Backup- und Compliance-Prozesse. Wer bislang Skripte betreibt, die Log-Dateien unter /var/lib/docker/containers direkt sichern oder archivieren, muss diese Prozesse beim Wechsel zu journald anpassen, weil die Logs dann nicht mehr als einzelne Textdateien vorliegen, sondern in der binären Journal-Datenbank gespeichert werden. Für Audit-Anforderungen, die eine unveränderliche Kopie der Rohlogs verlangen, ist ein regelmäßiger Export über journalctl --output=json in ein externes Archiv der pragmatische Ersatz für das bisherige Kopieren der json-file-Dateien.
8. Typische Fehler bei der Log-Driver-Wahl
Der häufigste Fehler ist, json-file ohne max-size und max-file im Produktivbetrieb laufen zu lassen. Dieses Versäumnis führt schleichend zu vollen Festplatten, oft erst bemerkt, wenn der Host bereits andere Probleme durch fehlenden Speicherplatz zeigt, etwa fehlschlagende Deployments oder eine MySQL-Instanz, die keine neuen Schreibvorgänge mehr ausführen kann.
# Common mistakes when choosing a Docker log driver
# WRONG: json-file without any size limits — grows unbounded
# logging:
# driver: "json-file"
# # no options — log file can fill the entire disk
# RIGHT: always cap size and file count explicitly
# logging:
# driver: "json-file"
# options:
# max-size: "10m"
# max-file: "5"
# WRONG: switching to journald without checking journald.conf limits
# journald.conf might have SystemMaxUse too small for container volume
# RIGHT: size the journal for the actual container log volume
# /etc/systemd/journald.conf
# SystemMaxUse=2G
# RuntimeMaxUse=512M
# WRONG: assuming docker logs behaves identically after switching drivers
# some drivers (e.g. journald) don't support all `docker logs` flags identically
# RIGHT: verify docker logs --since/--tail behavior after switching
Ein zweiter Fehler ist die Annahme, dass alle Log-Driver dieselben docker logs-Optionen identisch unterstützen. Manche Driver, etwa solche, die Logs ausschließlich an ein externes System weiterreichen, unterstützen docker logs gar nicht mehr, weil die Daten den lokalen Host verlassen, bevor Docker selbst darauf zugreifen könnte. Ein dritter Fehler ist eine zu klein bemessene Journal-Größe bei journald, wodurch Container-Logs ältere, wichtige System-Logs verdrängen, wenn kein ausreichender Speicherplatz für beide Zwecke eingeplant wurde.
Ein oft übersehener Aspekt bei der Wahl des Log-Drivers ist die Nachvollziehbarkeit über Container-Neustarts und Deployments hinweg. Bei json-file verschwindet die Log-Datei eines Containers zusammen mit dem Container, sofern kein separates Volume oder kein Log-Shipping eingerichtet ist, was nach einem Rolling-Update die Fehlersuche für den letzten Zustand vor dem Neustart erschwert. Bei journald bleiben die Einträge im zentralen Journal erhalten, solange die Journal-Rotation sie nicht verdrängt, unabhängig davon, ob der zugehörige Container noch existiert. Dieser Unterschied wird besonders bei häufigen Deployments in CI/CD-Pipelines relevant, wo Container in kurzen Abständen ersetzt werden und die Fehlersuche nach einem fehlgeschlagenen Deployment sonst ins Leere läuft.
9. json-file und journald im direkten Vergleich
Die Entscheidung zwischen den beiden verbreitetsten Log-Driver-Optionen hängt von der vorhandenen Infrastruktur und den Anforderungen an Integration und Performance ab.
| Kriterium | json-file | journald | Empfehlung |
|---|---|---|---|
| Rotation | Pro Container, manuell konfiguriert | Zentral über journald.conf | journald bei vielen Containern einfacher |
| Tool-Kompatibilität | Standard für Promtail, Filebeat | Braucht Journal-Input-Plugin | json-file bei bestehender Log-Pipeline |
| Systemd-Integration | Keine | Nativ über journalctl | journald bei systemd-zentrierten Teams |
| Portabilität | Überall, plattformunabhängig | Nur mit systemd verfügbar | json-file bei gemischten Betriebssystemen |
Für die meisten Docker-Umgebungen mit bereits etabliertem zentralem Logging über Loki oder Elasticsearch bleibt json-file mit expliziten Rotations-Limits die pragmatischste Wahl. journald lohnt sich vor allem dann, wenn die Infrastruktur ohnehin stark auf systemd setzt und journalctl bereits der zentrale Anlaufpunkt für Diagnose ist.
Abschließend lohnt sich der Blick auf gemischte Setups: Nichts spricht dagegen, einen kritischen Datenbank-Container mit json-file und engen Rotations-Limits zu betreiben, während ein Legacy-Service, der ohnehin über journalctl überwacht wird, weiterhin journald nutzt. Die Entscheidung muss nicht host- oder projektweit einheitlich getroffen werden, solange jeder Container einzeln bewusst konfiguriert ist und niemand sich blind auf die Docker-Standardeinstellung verlässt.
10. Zusammenfassung
Die Wahl des richtigen Docker-Log-Drivers zwischen json-file und journald hat direkte Auswirkungen auf Speicherverbrauch, Performance und Integrationsaufwand. json-file ist portabel, einfach zu verstehen und die Standardgrundlage für die meisten Log-Collector, verlangt aber explizite max-size- und max-file-Limits, um Festplatten nicht unkontrolliert zu füllen. journald integriert Container-Logs nativ in die systemd-Infrastruktur, zentralisiert Rotation und Größenbegrenzung, benötigt aber angepasste Collector-Konfigurationen.
Die richtige Entscheidung ist selten universell, sondern hängt von der vorhandenen Logging-Landschaft ab. Wer bereits Loki oder Elasticsearch mit JSON-basierten Collectors betreibt, bleibt meist bei json-file. Wer stark auf systemd setzt und journalctl im täglichen Betrieb nutzt, profitiert von der nahtlosen Integration durch journald. In beiden Fällen gilt: explizite Limits konfigurieren, statt sich auf Standardwerte zu verlassen.
Wer diesen Entscheidungsprozess einmal sauber dokumentiert, spart bei jedem neuen Service oder Host die erneute Grundsatzdiskussion und stellt sicher, dass alle Container einer Umgebung nach denselben nachvollziehbaren Kriterien konfiguriert werden.
Docker-Log-Driver json-file vs. journald — Das Wichtigste auf einen Blick
json-file
Portabel, JSON-Zeilenformat, Standard für Promtail und Filebeat, braucht explizite max-size/max-file Limits.
journald
Integriert in systemd-Journal, zentrale Rotation, durchsuchbar über journalctl, braucht Journal-Input-Plugins.
Rotation
json-file pro Container konfigurieren, journald zentral über journald.conf für den gesamten Host.
Entscheidungshilfe
Bestehende Log-Pipeline und Team-Vertrautheit mit systemd entscheiden meist mehr als reine Performance.
Die folgenden Fragen fassen die in der Praxis häufigsten Unsicherheiten rund um die Wahl und den Betrieb des passenden Log-Drivers zusammen und dienen als schnelle Referenz für Entscheidungen im Tagesgeschäft.