## Team-Entwicklungsumgebungen vereinheitlichen mit globalen [[Docker]]-Daemon-Einstellungen {#sec-b2e039a7f45a} Egal ob lokal oder auf dem Server – wer Docker nutzt, kennt das Problem: Immer wieder die gleichen Einstellungen in `docker-compose.yml` für jedes Projekt kopieren und einfügen. * DNS immer auf `1.1.1.1`, `8.8.8.8` einstellen * Den Log-Treiber auf `json-file` + `max-size=10m` festlegen * Proxys, insecure registries, Standard-Netzwerkbereiche und mehr… Solche Einstellungen sind keine spezifischen Container-Konfigurationen, sondern **„Standardwerte für den gesamten Host“**. Wenn man sie dorthin auslagert, wird die Verwaltung erheblich einfacher. Genau diese Rolle übernimmt die **globale Docker-Daemon-Konfiguration (`daemon.json`)**. Im Folgenden werden wir uns ansehen: * Welche Datei * Wo sie erstellt werden muss * Wie sie zu konfigurieren ist * In welchen Situationen sie für welche Entwickler/Teams nützlich ist zusammenfassen.
## 1. Zwei Wege zur Konfiguration des Docker-Daemons \{\#sec\-7390246eab38\} {#sec-9c4e8fa15a41} Der Docker-Daemon (`dockerd`) lässt sich grundsätzlich auf zwei Arten konfigurieren: 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 beispielsweise der Log-Treiber sowohl über das `--log-driver`-Flag als auch in der `daemon.json` definiert wird, bricht Docker mit einem Fehler beim Start ab. Für die Vereinheitlichung von Team-/Serverumgebungen wird in der Regel empfohlen: > „Sammeln Sie so viel wie möglich in der `daemon.json` und verwenden Sie Flags nur minimal.“ empfiehlt sich. ## 2. Speicherort der `daemon.json` {#sec-97a08839a2de} Der Speicherort der Datei ist **`/etc/docker/daemon.json`**. Dies gilt natürlich für Linux-Systeme. Es mag Nutzer geben, die Docker außerhalb von Linux-Umgebungen verwenden. Da ich es jedoch ausschließlich unter Linux nutze, bin ich mit anderen Betriebssystemen weniger vertraut. Die Standardpfade pro Betriebssystem lassen sich jedoch übersichtlich wie folgt zusammenfassen: | Umgebung | Standardpfad | Anmerkung | | --- | ----- | --- | | Linux (Standardinstallation) | `/etc/docker/daemon.json` | Häufigster Fall | | Linux (Docker über Snap installiert) | `/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 und nutzen. ## 3. Grundlegendes Nutzungsmuster: „Datei erstellen → Daemon neu starten“ \{\#sec\-bffe465cc36f\} {#sec-875278239b12} Unter Linux sieht der typische Workflow so aus: 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" } } ``` 1. **Vorabvalidierung** der Konfigurationsdatei ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # Wenn "configuration OK" erscheint, ist alles in Ordnung :contentReference[oaicite:7]{index=7} ``` 1. Docker-Daemon **neu starten** ```bash sudo systemctl restart docker ``` Alle neu gestarteten Container erben diese globalen Einstellungen nun **als Standardwerte**, sofern keine spezifischen Konfigurationen vorliegen. ## 4. Hauptkonfiguration: DNS-Server global festlegen \{\#sec\-d9c2238a423f\} {#sec-c284419e45cd} ### 4.1 Warum DNS global festlegen? {#sec-78011cf35f17} Wenn Container häufig Probleme haben, externe APIs nicht zu finden oder interne Domains nicht aufzulösen, liegt dies meist daran, dass sie stark von den **DNS-Einstellungen und der Umgebung des Hosts abhängen**. Zum Beispiel: * Das gesamte Team möchte Cloudflare DNS ( `1.1.1.1` ) verwenden. * Es gibt Endpunkte, die nur über den internen DNS-Server des Unternehmens erreichbar sind. In solchen Fällen ist es viel bequemer, dies direkt auf Docker-Daemon-Ebene zu vereinheitlichen, anstatt **in jedem Projekt erneut `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 Root-Objekts `{ ... }` hinzu. > ⚠️ **Achtung:** DNS-Einstellungen werden innerhalb des Containers in `/etc/resolv.conf` übernommen. Sie wirken sich nicht sofort auf bereits laufende Container aus, sondern **erst auf neu gestartete Container**. ## 5. Hauptkonfiguration 2 – Globaler Log-Treiber & Optionen \{\#sec\-360ddebc7b6c\} {#sec-fe09c43b83b1} Container-Logs werden standardmäßig über den `json-file`-Treiber unter `/var/lib/docker/containers/...` abgelegt. Eine globale Änderung ermöglicht es, Folgendes **einheitlich auf alle Container anzuwenden**: * Log-Format * Log-Speicherort * Log-Rotationsrichtlinie ### 5.1 Standard-json-file-Treiber + Rotation {#sec-26c5fb9056b5} Das häufigste Muster ist, den `json-file`-Treiber zu nutzen und dabei eine Rotation zu konfigurieren, um ein Überlaufen der Festplatte zu verhindern. ```json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } } ``` Damit erreichen Sie: * Die maximale Log-Dateigröße pro Container beträgt `10MB`. * Es werden maximal `5` Dateien aufbewahrt. * Überschüssige Dateien werden automatisch gelöscht. ### 5.2 Treiber für zentrale Log-Sammlung (Fluentd, Journald etc.) {#sec-e7499afd6f5d} Als Plattform- oder Infrastrukturteam möchte man oft die Logs aller Container an ein **zentrales Logging-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. Ich persönlich schätze auch den **`journald`-Treiber** sehr. In einer systemd-basierten Linux-Umgebung lassen sich alle Anwendungs- und Docker-Container-Logs an einer zentralen Stelle in Journald sammeln, was eine einheitliche Abfrage, Filterung und Verwaltung der Aufbewahrungsrichtlinien allein mit `journalctl` ermöglicht. Wenn Sie `journald` als globalen Log-Treiber nutzen möchten, könnten Sie es beispielsweise so konfigurieren: ```json { "log-driver": "journald", "log-opts": { "tag": "{{.Name}}" } } ``` Da hier `tag` als Container-Name verwendet wird: * Sie können **Echtzeit-Logs schnell überfliegen** in der Form `journalctl -f | grep {container_name}`. * Durch die Kombination mit Optionen wie `--since "10m ago"` können Sie **Logs ab einem bestimmten Zeitpunkt anzeigen**. * Mit der Option `-t` (nach Tag/Bezeichner) wie in `journalctl -f -t {container_name}` können Sie **gezielt Logs eines bestimmten Containers** anzeigen. Natürlich ist es auch möglich, Logs nach Units wie `journalctl -u docker.service` anzuzeigen. Das Filtern nach Containernamen ist jedoch intuitiver und erfordert weniger Tippaufwand, weshalb es in der Praxis deutlich häufiger zum Einsatz kommt. ### 5.3 Beziehung zu Compose / `docker run` {#sec-8d284e8a0dfd} * **Globale `log-driver` + `log-opts`** dienen als „Standardwerte“. * 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 empfohlen: * Gemeinsame Werte in `daemon.json` * Spezielle Dienste nur individuell überschreiben ist die empfohlene Konfiguration. *** ## 6. Hauptkonfiguration 3 – Globale Netzwerkeinstellungen wie Proxy, Insecure Registry \{\#sec\-0d687ac65460\} {#sec-bc2f973bcb11} Es gibt weitere Optionen, die häufig in der globalen Konfiguration zum Einsatz kommen. ### 6.1 Proxy-Einstellungen {#sec-753696ea7a1f} Wenn externe Verbindungen nur über einen Unternehmens-Proxy möglich sind, können Sie den Proxy **auf Daemon-Ebene konfigurieren**, anstatt jedes Mal Umgebungsvariablen setzen zu müssen. ```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, sei es beim Pull von Images oder bei der Netzwerknutzung während des Builds. ### 6.2 Insecure Registry {#sec-fe7d1c14ce8d} Wenn Sie eine Registry ohne TLS verwenden müssen (z.B. für die interne Entwicklung): ```json { "insecure-registries": ["my-registry.local:5000"] } ``` Da dies ein Sicherheitsrisiko darstellen kann, sollte es **nur in internen Testumgebungen** verwendet werden. *** ## 7. Hauptkonfiguration 4 – Standard-Netzwerkbereich, Speicher-Treiber etc. \{\#sec\-3598d5fb02d3\} {#sec-efc333459aa9} Weitere infrastrukturelle Optionen: ### 7.1 Standard-Bridge-Netzwerkbereich anpassen {#sec-00d891d2b55d} Wenn Sie IP-Konflikte mit Ihrem VPN oder dem Unternehmensnetzwerk vermeiden möchten: ```json { "default-address-pools": [ { "base": "10.20.0.0/16", "size": 24 } ] } ``` Dadurch nutzt Docker beim Erstellen eines neuen Bridge-Netzwerks den Bereich `10.20.x.0/24`. ### 7.2 Speicher-Treiber erzwingen {#sec-04d867ec1442} Der Standard-Speicher-Treiber kann je nach Linux-Distribution variieren. Hat sich Ihr Team auf die ausschließliche Nutzung von `overlay2` geeinigt, können Sie dies so festlegen: ```json { "storage-driver": "overlay2" } ``` > Beachten Sie, dass die tatsächlich unterstützten Speicher-Treiber je nach Betriebssystem und Kernel variieren. Überprüfen Sie daher unbedingt die `dockerd`-Dokumentation und die Anleitung Ihrer Distribution. *** ## 8. Wenn Sie dieses „Déjà-vu“ kennen, sollten Sie jetzt handeln \{\#sec\-807a100451aa\} {#sec-e2c8a9ca03d5} Sie müssen die komplexen Infrastrukturgegebenheiten nicht bis ins Detail kennen. Wenn Sie in letzter Zeit eine der folgenden Erfahrungen gemacht haben, ist es höchste Zeit, die `daemon.json` anzupassen: * **Sie durchsuchen bei jedem neuen Projekt die `docker-compose.yml` und kopieren Log-Einstellungen:** Wenn Sie die `max-size`-, `max-file`-Einstellungen aus Ihrem alten Code heraussuchen und erneut einfügen, verschwenden Sie bereits wertvolle Zeit. Einmal global definiert, starten alle Container automatisch im „Diät“-Modus. * **Ein Container, der im Büro einwandfrei lief, hat im Café oder über VPN keine Internetverbindung mehr:** Der klassische Fall von „Auf meinem lokalen Rechner ging es doch!“. 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 eine globale DNS-Festlegung die Lösung. * **Sie sind verwirrt, weil Sie die Einstellungen unzähliger Serverknoten einzeln anpassen müssen:** Kämpfen Sie mit „Geister-Bugs“, die durch leicht abweichende Docker-Einstellungen auf jedem Server entstehen? Eine einzige `daemon.json`-Datei genügt, um alle Server wie eine gut geölte Maschine nach denselben Regeln arbeiten zu lassen. *** > Wenn Sie wiederkehrende Konfigurationen leid sind oder die Fehlersuche aufgrund von Umgebungsänderungen Ihnen auf die Nerven geht, ist dies der perfekte Zeitpunkt, um diese Einstellungen zu implementieren. ## 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, insecure registry, Standard-Netzwerkbereiche, Speicher-Treiber… * Globale Einstellungen sind nützlich für wiederkehrende Konfigurationen und beim Einsatz vieler Nodes in verschiedenen Umgebungen. Wenn Sie weiterhin dieselben Optionen in `docker-compose.yml` oder `docker run` verwenden, **ist es vielleicht an der Zeit, diese einmal in die `daemon.json` zu verschieben.** ![Bild der Docker-Daemon-JSON-Einstellung](https://blog.mikihands.com/media/editor_temp/6/00f7dbc8-f71e-485b-b9a9-e9514af1ba73.png)