Docker: Team-Entwicklungsumgebungen mit globalen Daemon-Einstellungen vereinheitlichen
Ob lokal oder auf dem Server: Wer Docker nutzt, wird feststellen, dass immer wieder dieselben Einstellungen in der docker-compose.yml pro Projekt kopiert und eingefügt werden müssen.
- Ständig DNS auf
1.1.1.1,8.8.8.8festlegen - Den Log-Treiber auf
json-file+max-size=10mfixieren - Proxy, unsichere Registrierung, Standard-Netzwerkbereiche und mehr…
Solche Dinge lassen sich viel einfacher verwalten, wenn man sie nicht als individuelle Containereinstellungen, sondern als „Standardwerte für den gesamten Host“ definiert.
Genau diese Rolle übernimmt die globale Docker-Daemon-Konfiguration (daemon.json).
Im Folgenden werde ich erläutern:
- Welche Datei
- Wo sie erstellt werden sollte
- Wie sie zu konfigurieren ist
- Und für welche Entwickler/Teams sie unter welchen Umständen nützlich ist.
1. Zwei Methoden zur Konfiguration des Docker-Daemons
Der Docker-Daemon (dockerd) kann grundsätzlich auf zwei Arten konfiguriert werden:
- Verwendung einer JSON-Konfigurationsdatei (
daemon.json) ← Empfohlen - Übergabe von Optionen als CLI-Flags beim Start von
dockerd
Beide Methoden können kombiniert werden, aber wenn dieselbe Option in beiden Konfigurationen angegeben wird, startet der Daemon überhaupt nicht.
Wenn Sie beispielsweise den Log-Treiber sowohl über das --log-driver-Flag als auch in der daemon.json festlegen, wird Docker beim Start mit einem Fehler beendet.
Zur Vereinheitlichung von Team-/Serverumgebungen wird in der Regel empfohlen:
„So viel wie möglich in die
daemon.jsonpacken und Flags auf ein Minimum beschränken.“
2. Speicherort der daemon.json
Der Dateipfad ist /etc/docker/daemon.json. Dies gilt natürlich für Linux.
Es mag Nutzer geben, die Docker in anderen Umgebungen als Linux verwenden. Da ich es jedoch ausschließlich unter Linux nutze, bin ich mit anderen Betriebssystemen weniger vertraut. Die Standardpfade pro Betriebssystem sind jedoch übersichtlich in der folgenden Tabelle zusammengefasst:
| Umgebung | Standardpfad | Anmerkung |
|---|---|---|
| Linux (Standardinstallation) | /etc/docker/daemon.json |
Der häufigste Fall |
| Linux (per Snap installiertes Docker) | /var/snap/docker/current/config/daemon.json |
Ubuntu Snap-Paket |
| Windows Server / Docker Engine | C:\ProgramData\Docker\config\daemon.json |
|
| Docker Desktop (Mac / Windows) | ~/.docker/daemon.json |
- Diese Datei existiert standardmäßig möglicherweise nicht. Falls sie fehlt, können Sie sie einfach selbst erstellen.
3. Grundlegendes Nutzungsmuster: „Datei erstellen → Daemon neu starten“
Unter Linux ist der typische Workflow wie folgt:
daemon.jsonerstellen/bearbeiten
{
"dns": ["1.1.1.1", "8.8.8.8"],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
- Vorabvalidierung der Konfigurationsdatei
sudo dockerd --validate --config-file=/etc/docker/daemon.json
# Wenn "configuration OK" erscheint, ist alles in Ordnung
- Docker-Daemon neustarten
sudo systemctl restart docker
Von nun an erben alle neu gestarteten Container diese globalen Einstellungen als Standardwerte, sofern keine individuellen Einstellungen vorgenommen werden.
4. Haupteinstellung: DNS-Server global festlegen
4.1 Warum DNS global konfigurieren?
Wenn Container häufig Probleme haben, „externe APIs nicht zu finden“ oder „interne Domains nicht aufzulösen“, liegt das meist daran, dass sie von den DNS-Einstellungen/der Umgebung des Hosts abhängig sind.
Zum Beispiel:
- Das gesamte Team möchte Cloudflare DNS (
1.1.1.1) nutzen. - Es gibt Endpunkte, die nur über den internen DNS-Server des Unternehmens erreichbar sind.
In solchen Fällen ist es viel bequemer, die DNS-Einstellungen auf der Docker-Daemon-Ebene zu vereinheitlichen, anstatt in jedem Projekt dns: in die docker-compose.yml einzufügen.
4.2 Konfigurationsbeispiel (daemon.json)
{
"dns": ["1.1.1.1", "8.8.8.8"]
}
Wenn bereits eine daemon.json existiert, fügen Sie einfach den Eintrag "dns": [...] innerhalb des Wurzel-Objekts { ... } hinzu.
⚠️ Achtung: DNS-Einstellungen werden in der
/etc/resolv.confim Container übernommen. Sie werden nicht sofort auf bereits laufende Container angewendet, sondern erst auf neu gestartete Container.
5. Haupteinstellung 2 – Globaler Log-Treiber & Optionen
Container-Logs werden standardmäßig über den json-file-Treiber unter /var/lib/docker/containers/... gespeichert. Wenn dies global geändert wird, können Sie:
- das Log-Format
- den Speicherort der Logs
- und die Log-Rotationsrichtlinie
für alle Container einheitlich anwenden.
5.1 Standard json-file Treiber + Rotation
Das häufigste Muster ist: „Einfach json-file verwenden, aber mit Rotations-Einstellungen, damit die Festplatte nicht überläuft.“
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
Damit wird erreicht:
- Die Log-Dateigröße pro Container beträgt maximal
10 MB. - Es werden maximal
5Dateien vorgehalten. - Überschüssige Dateien werden automatisch gelöscht.
5.2 Treiber für die zentrale Log-Erfassung (Fluentd, Journald etc.)
Plattform- oder Infrastrukturteams möchten oft die Logs aller Container an ein zentrales Log-System senden.
Wenn Sie beispielsweise Fluentd verwenden:
{
"log-driver": "fluentd",
"log-opts": {
"fluentd-address": "localhost:24224",
"tag": "{{.Name}}"
}
}
Auf diese Weise werden die Logs aller Container automatisch an Fluentd gesendet, ohne dass ein separates docker run --log-driver=... erforderlich ist.
Persönlich mag ich auch den journald-Treiber sehr. In systemd-basierten Linux-Umgebungen können alle Anwendungs- und Docker-Container-Logs an einer zentralen Stelle (journald) gesammelt werden, wodurch die Abfrage, Filterung und Aufbewahrungsrichtlinien allein mit journalctl vereinheitlicht werden können.
Wenn Sie journald als globalen Log-Treiber verwenden möchten, können Sie es beispielsweise so konfigurieren:
{
"log-driver": "journald",
"log-opts": {
"tag": "{{.Name}}"
}
}
Da tag hier als Container-Name verwendet wird, können Sie:
- Echtzeit-Logs schnell überblicken im Format
journalctl -f | grep {container_name} - Optionen wie
--since "10m ago"kombinieren, um nur Logs ab einem bestimmten Zeitpunkt anzuzeigen - und mit der Option
-t(basierend auf Tag/Identifier) wiejournalctl -f -t {container_name}gezielt Logs eines bestimmten Containers anzeigen.
Selbstverständlich ist es auch möglich, Logs einheitenbasiert mit journalctl -u docker.service anzuzeigen. Das Filtern nach Container-Namen ist jedoch intuitiver und erfordert weniger Tipparbeit, weshalb es in der Praxis viel häufiger eingesetzt wird.
5.3 Beziehung zu Compose / docker run
- Der globale
log-driver+log-optsdient als „Standardwert“ - Wenn für einzelne Container
logging:(Compose) oder--log-driver,--log-opt(CLI) angegeben wird, überschreibt dies die globalen Einstellungen nur für diesen Container.
Strategisch wird empfohlen:
- Gemeinsame Werte in der
daemon.jsonzu definieren - und nur spezielle Dienste individuell zu überschreiben.
6. Haupteinstellung 3 – Globale Netzwerkeinstellungen wie Proxy, Insecure Registry
Es gibt weitere Optionen, die häufig in den globalen Einstellungen verwendet werden.
6.1 Proxy-Einstellungen
Wenn der Zugriff nach außen nur über einen internen Unternehmensproxy möglich ist, können Sie den Proxy auf Daemon-Ebene konfigurieren, anstatt jedes Mal Umgebungsvariablen hinzuzufügen.
{
"proxies": {
"http-proxy": "http://proxy.example.com:3128",
"https-proxy": "http://proxy.example.com:3128",
"no-proxy": "localhost,127.0.0.1,.corp.example.com"
}
}
Auf diese Weise folgt der Docker-Daemon diesen Proxy-Einstellungen, wenn er Images abruft oder das Netzwerk während des Builds verwendet.
6.2 Insecure Registry
Wenn Sie unbedingt eine Registry ohne TLS verwenden müssen (z. B. für die interne Entwicklung):
{
"insecure-registries": ["my-registry.local:5000"]
}
Dies kann ein Sicherheitsrisiko darstellen, daher sollte es nur in internen Testumgebungen verwendet werden.
7. Haupteinstellung 4 – Standard-Netzwerkbereiche, Storage-Treiber etc.
7.1 Anpassen des Standard-Bridge-Netzwerkbereichs
Wenn Sie Überschneidungen von IP-Adressen mit VPNs oder internen Unternehmensnetzwerken vermeiden möchten:
{
"default-address-pools": [
{
"base": "10.20.0.0/16",
"size": 24
}
]
}
Dadurch verwendet Docker beim Erstellen neuer Bridge-Netzwerke den Bereich 10.20.x.0/24.
7.2 Erzwingen eines Storage-Treibers
Der Standard-Storage-Treiber kann je nach Linux-Distribution variieren. Wenn Ihr Team beschlossen hat, nur overlay2 zu verwenden:
{
"storage-driver": "overlay2"
}
Die tatsächlich unterstützten Storage-Treiber variieren je nach Betriebssystem und Kernel. Überprüfen Sie daher unbedingt die
dockerd-Dokumentation und die Distributionsanleitung.
8. Wenn Sie diese „Déjà-vus“ erleben, sollten Sie jetzt handeln
Sie müssen keine komplexen Infrastrukturdetails kennen. Wenn Sie kürzlich die folgenden Erfahrungen gemacht haben, ist es höchste Zeit, sich um die daemon.json zu kümmern.
- Bei jedem neuen Projekt durchsuchen Sie die
docker-compose.ymlund kopieren/einfügen Log-Einstellungen: Wenn Sie Einstellungen wiemax-sizeodermax-fileaus dem Code von gestern heraussuchen und erneut einfügen, verschwenden Sie bereits wertvolle Zeit. Einmal global definiert, starten alle Container automatisch im „Diät-Modus“. - Container, die im Büro einwandfrei funktionieren, haben in einer Café- oder VPN-Umgebung keinen Internetzugang: Das ist der klassische Fall von „Auf meinem lokalen System hat es funktioniert!“. Wenn Sie möchten, dass Ihre Container unabhängig von den DNS-Einstellungen des Hosts in jeder Netzwerkumgebung konsistent mit der Außenwelt kommunizieren, ist die globale DNS-Fixierung die richtige Lösung.
- Sie sind völlig überfordert, weil Sie die Einstellungen zahlreicher Server-Knoten einzeln anpassen müssen: Kämpfen Sie mit „Geister-Bugs“, die durch subtil unterschiedliche Docker-Einstellungen auf jedem Server entstehen? Wenn Sie nur eine
daemon.json-Datei bereitstellen, werden alle Server nach denselben Regeln betrieben.
Wenn Sie wiederkehrende Einstellungen leid sind oder die ständigen Probleme durch Umgebungsänderungen satt haben, ist dies der perfekte Zeitpunkt, diese Konfiguration einzuführen.
Zusammenfassung
- Die globalen Standardwerte von Docker werden in der
daemon.jsonverwaltet. - Der Speicherort ist normalerweise
/etc/docker/daemon.json. - Beispiele für typische globale Einstellungen:
- DNS:
"dns": ["1.1.1.1", "8.8.8.8"] - Log-Treiber:
"log-driver": "json-file","log-opts": {...} - Proxy, unsichere Registrierung, Standard-Netzwerkbereiche, Storage-Treiber…
- DNS:
- Globale Einstellungen sind nützlich für wiederkehrende Konfigurationen und beim Einsatz vieler Knoten in verschiedenen Umgebungen.
Wenn Sie ständig dieselben Optionen in Ihrer docker-compose.yml oder bei docker run verwenden,
könnte es an der Zeit sein, diese einmal in die daemon.json zu verschieben.
