## [[Docker]]: Team-Entwicklungsumgebungen mit globalen Daemon-Einstellungen vereinheitlichen {#sec-b2e039a7f45a} 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.8` festlegen * Den Log-Treiber auf `json-file` + `max-size=10m` fixieren * 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 {#sec-9c4e8fa25a41} Der [[Docker]]-Daemon (`dockerd`) kann grundsätzlich auf zwei Arten konfiguriert werden: 1. **Verwendung einer JSON-Konfigurationsdatei (`daemon.json`)** ← *Empfohlen* 2. Ü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.json` packen und Flags auf ein Minimum beschränken.“ ## 2. Speicherort der `daemon.json` {#sec-97a08839a2de} 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“ {#sec-875278239b12} Unter Linux ist der typische Workflow wie folgt: 1. **`daemon.json` erstellen/bearbeiten** ```json { "dns": ["1.1.1.1", "8.8.8.8"], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } ``` 2. **Vorabvalidierung** der Konfigurationsdatei ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # Wenn "configuration OK" erscheint, ist alles in Ordnung ``` 3. [[Docker]]-Daemon **neustarten** ```bash 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 {#sec-c284419e45cd} ### 4.1 Warum DNS global konfigurieren? {#sec-78011cf35f17} 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`) {#sec-2a85a418cbea} ```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.conf` im Container übernommen. Sie werden nicht sofort auf bereits laufende Container angewendet, sondern **erst auf neu gestartete Container**. ## 5. Haupteinstellung 2 – Globaler Log-Treiber & Optionen {#sec-fe09c43b83b1} 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 {#sec-26c5fb9056b5} Das häufigste Muster ist: „Einfach `json-file` verwenden, aber mit Rotations-Einstellungen, damit die Festplatte nicht überläuft.“ ```json { "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 `5` Dateien vorgehalten. * Überschüssige Dateien werden automatisch gelöscht. ### 5.2 Treiber für die zentrale Log-Erfassung (Fluentd, Journald etc.) {#sec-e7499afd6f5d} Plattform- oder Infrastrukturteams möchten oft die Logs aller Container an ein **zentrales Log-System** senden. Wenn Sie beispielsweise Fluentd verwenden: ```json { "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: ```json { "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) wie `journalctl -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` {#sec-8d284e8a0dfd} * Der **globale `log-driver` + `log-opts`** dient 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.json` zu definieren * und nur spezielle Dienste individuell zu überschreiben. *** ## 6. Haupteinstellung 3 – Globale Netzwerkeinstellungen wie Proxy, Insecure Registry {#sec-bc2f973bcb11} Es gibt weitere Optionen, die häufig in den globalen Einstellungen verwendet werden. ### 6.1 Proxy-Einstellungen {#sec-753696ea7a1f} 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. ```json { "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 {#sec-fe7d1c14ce8d} Wenn Sie unbedingt eine Registry ohne TLS verwenden müssen (z. B. für die interne Entwicklung): ```json { "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. {#sec-efc333459aa9} ### 7.1 Anpassen des Standard-Bridge-Netzwerkbereichs {#sec-00d891d2b55d} Wenn Sie Überschneidungen von IP-Adressen mit VPNs oder internen Unternehmensnetzwerken vermeiden möchten: ```json { "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 {#sec-04d867ec1442} Der Standard-Storage-Treiber kann je nach Linux-Distribution variieren. Wenn Ihr Team beschlossen hat, nur `overlay2` zu verwenden: ```json { "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 {#sec-e2c8a9ca03d5} 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.yml` und kopieren/einfügen Log-Einstellungen:** Wenn Sie Einstellungen wie `max-size` oder `max-file` aus 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 {#sec-857c80428df3} * Die globalen Standardwerte von [[Docker]] werden in der **`daemon.json`** verwaltet. * 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… * 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.** ![Abbildung der Docker-Daemon-JSON-Einstellungen](https://blog.mikihands.com/media/editor_temp/6/00f7dbc8-f71e-485b-b9a9-e9514af1ba73.png)