## [[Docker]] De teamontwikkelomgeving uniformeren met de globale instellingen van de Docker daemon {#sec-b2e039a7f45a} Of je nu Docker lokaal of op een server gebruikt, je zult merken dat je steeds dezelfde instellingen kopieert en plakt in `docker-compose.yml` voor elk project. * Altijd DNS instellen op `1.1.1.1` en `8.8.8.8` * De log driver vastzetten op `json-file` + `max-size=10m` * Proxy, insecure registry, standaard netwerkbereik, enzovoort… Dergelijke instellingen kunnen veel eenvoudiger worden beheerd als ze niet als **individuele containerinstellingen** worden gedefinieerd, maar als **"host-brede standaardwaarden"**. Dit is precies de rol van de **globale Docker daemon-configuratie (`daemon.json`)**. Hieronder zullen we bespreken: * Welk bestand * Waar het moet worden aangemaakt * Hoe het moet worden geconfigureerd * Voor welke ontwikkelaars/teams het nuttig is en in welke situaties uitgebreid behandelen.
## 1. Twee manieren om de Docker daemon te configureren {#sec-9c4e8fa25a41} De Docker daemon (`dockerd`) kan hoofdzakelijk op twee manieren worden geconfigureerd: 1. **Gebruik van het JSON-configuratiebestand (`daemon.json`)** ← *Aanbevolen* 2. Opties doorgeven via **CLI-vlaggen** bij het uitvoeren van `dockerd` Hoewel beide methoden gecombineerd kunnen worden, zal de daemon **niet opstarten als dezelfde optie in beide configuraties wordt gespecificeerd**. Als je bijvoorbeeld de log driver zowel via de `--log-driver` vlag als in `daemon.json` instelt, zal Docker een fout genereren en stoppen tijdens het opstarten. Voor het uniformeren van team-/serveromgevingen wordt doorgaans aangeraden: > "Verzamel zoveel mogelijk in `daemon.json` en gebruik vlaggen minimaal." Dit wordt aanbevolen. ## 2. Locatie van `daemon.json` {#sec-97a08839a2de} De locatie van het bestand is **`/etc/docker/daemon.json`**. Dit is uiteraard voor Linux-systemen. Hoewel ik niet zeker weet of veel mensen Docker buiten Linux gebruiken – ikzelf gebruik het alleen op Linux en ben minder bekend met andere OS'en – is hier een handig overzicht van de standaardlocaties per besturingssysteem: | Omgeving | Standaardpad | Opmerkingen | | --- | ----- | --- | | Linux (standaard installatie) | `/etc/docker/daemon.json` | Meest voorkomende geval | | Linux (Docker geïnstalleerd met snap) | `/var/snap/docker/current/config/daemon.json` | Ubuntu snap-pakket | | Windows Server / Docker Engine | `C:\ProgramData\Docker\config\daemon.json` | | | Docker Desktop (Mac / Windows) | `~/.docker/daemon.json` | | * Dit bestand bestaat mogelijk **standaard niet; als het ontbreekt, kun je het handmatig aanmaken** en gebruiken. ## 3. Basisgebruikspatroon: "Bestand aanmaken → Daemon herstarten" {#sec-875278239b12} Voor Linux is de typische workflow als volgt: 1. **`daemon.json` aanmaken/wijzigen** ```json { "dns": ["1.1.1.1", "8.8.8.8"], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } ``` 1. **Valideer** het configuratiebestand **vooraf** ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # Als "configuration OK" verschijnt, is het correct ``` 1. **Herstart** de Docker daemon ```bash sudo systemctl restart docker ``` Vanaf nu zullen nieuw opgestarte containers deze globale instellingen **als standaardwaarden overnemen**, tenzij anders geconfigureerd. ## 4. Belangrijke instelling: DNS-servers globaal vastzetten {#sec-c284419e45cd} ### 4.1 Waarom DNS globaal instellen? {#sec-78011cf35f17} Als je vaak problemen ondervindt waarbij containers 'vreemd genoeg externe API's niet kunnen vinden' of 'interne domeinen niet worden opgelost', komt dit meestal doordat ze **afhankelijk zijn van de DNS-instellingen/omgeving van de host**. Bijvoorbeeld: * Het hele team wil Cloudflare DNS (`1.1.1.1`) gebruiken * Er zijn endpoints die alleen toegankelijk zijn via de interne DNS-server van het bedrijf In dergelijke gevallen is het veel handiger om de DNS-instellingen op het niveau van de Docker daemon te uniformeren, **in plaats van elke keer `dns:` toe te voegen aan `docker-compose.yml` voor elk project**. ### 4.2 Configuratievoorbeeld (`daemon.json`) {#sec-2a85a418cbea} ```json { "dns": ["1.1.1.1", "8.8.8.8"] } ``` Als er al een `daemon.json` bestaat, kun je het item `"dns": [...]` toevoegen binnen de root `{ ... }`. > ⚠️ **Let op:** DNS-instellingen worden in de container weerspiegeld in `/etc/resolv.conf`. Ze worden niet direct toegepast op reeds draaiende containers, maar **alleen op nieuw gestarte containers**. ## 5. Belangrijke instelling 2 – Globale configuratie van logging drivers & opties {#sec-fe09c43b83b1} Containerlogs worden standaard opgeslagen onder `/var/lib/docker/containers/...` via de `json-file` driver. Door dit globaal te wijzigen, kun je: * Logformaat * Logopslaglocatie * Logrotatiebeleid **uniform toepassen op alle containers**. ### 5.1 Standaard `json-file` driver + rotatie {#sec-26c5fb9056b5} Het meest voorkomende patroon is "gewoon de `json-file` driver gebruiken, maar met rotatie-instellingen om te voorkomen dat de schijf vol raakt". ```json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } } ``` Met deze instelling geldt dat: * De logbestandsgrootte per container maximaal `10MB` bedraagt * Er maximaal `5` bestanden worden bewaard * Overtollige bestanden automatisch worden verwijderd. ### 5.2 Drivers voor centrale logverzameling (fluentd, journald, enz.) {#sec-e7499afd6f5d} Platform- of infrastructuurteams willen vaak de logs van alle containers naar een **centraal loggingsysteem** sturen. Als je bijvoorbeeld Fluentd gebruikt: ```json { "log-driver": "fluentd", "log-opts": { "fluentd-address": "localhost:24224", "tag": "{{.Name}}" } } ``` Met deze instelling worden de logs van alle containers automatisch naar Fluentd verzonden, zonder dat een aparte `docker run --log-driver=...` nodig is. Persoonlijk ben ik ook erg gecharmeerd van de `journald` driver. In een systemd-gebaseerde Linux-omgeving kun je zowel applicatielogs als Docker-containerlogs op één plek in `journald` verzamelen, en zo het bekijken, filteren en het bewaarbeleid uniformeren met alleen `journalctl`. Als je `journald` als globale log driver wilt gebruiken, kun je dit bijvoorbeeld als volgt configureren: ```json { "log-driver": "journald", "log-opts": { "tag": "{{.Name}}" } } ``` Doordat hier `tag` als containernaam wordt gebruikt, kun je: * **Snel live logs bekijken** in de vorm van `journalctl -f | grep {container_name}` * Door opties zoals `--since "10m ago"` te combineren, **alleen logs vanaf een specifiek tijdstip bekijken** * En met de `-t` optie (op basis van tag/identifier), zoals `journalctl -f -t {container_name}`, **specifieke containerlogs selecteren en bekijken**. Natuurlijk is het ook mogelijk om per unit te kijken, zoals met `journalctl -u docker.service`, maar filteren op containernaam is intuïtiever en vereist minder typwerk, waardoor het in de praktijk veel vaker wordt gebruikt. ### 5.3 Relatie met Compose / `docker run` {#sec-8d284e8a0dfd} * De **globale `log-driver` + `log-opts`** fungeren als "standaardwaarden" * Als je `logging:` (Compose) of `--log-driver`, `--log-opt` (CLI) opgeeft voor een individuele container, **overschrijft dit alleen die specifieke container** Strategisch gezien: * Gemeenschappelijke waarden in `daemon.json` * Alleen specifieke services individueel overschrijven Dit wordt aanbevolen. *** ## 6. Belangrijke instelling 3 – Globale netwerkinstellingen zoals proxy en insecure registry {#sec-bc2f973bcb11} Er zijn nog andere opties die vaak worden gebruikt in de globale instellingen. ### 6.1 Proxy-instellingen {#sec-753696ea7a1f} Als externe toegang alleen mogelijk is via een interne proxy, kun je de **proxy op daemon-niveau configureren** in plaats van elke keer omgevingsvariabelen toe te voegen. ```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" } } ``` Op deze manier volgt de Docker daemon deze proxy-instellingen bij het pullen van images of bij het gebruik van het netwerk tijdens het bouwen. ### 6.2 Insecure registry {#sec-fe7d1c14ce8d} Als je absoluut een registry zonder TLS moet gebruiken (bijvoorbeeld voor interne ontwikkeling): ```json { "insecure-registries": ["my-registry.local:5000"] } ``` Dit kan een beveiligingsrisico vormen, dus wees voorzichtig en gebruik het **alleen in interne testomgevingen**. *** ## 7. Belangrijke instelling 4 – Standaard netwerkbereik, storage driver, enz. {#sec-efc333459aa9} ### 7.1 Standaard bridge netwerkbereik aanpassen {#sec-00d891d2b55d} Als je wilt voorkomen dat IP-adressen overlappen met je VPN of interne bedrijfsnetwerk: ```json { "default-address-pools": [ { "base": "10.20.0.0/16", "size": 24 } ] } ``` Hiermee zal Docker het `10.20.x.0/24` bereik gebruiken wanneer het een nieuw bridge-netwerk aanmaakt. ### 7.2 Storage driver afdwingen {#sec-04d867ec1442} De standaard storage driver kan variëren afhankelijk van de Linux-distributie. Als het team heeft besloten om alleen `overlay2` te gebruiken: ```json { "storage-driver": "overlay2" } ``` > De daadwerkelijk ondersteunde storage drivers variëren per OS/kernel, dus raadpleeg altijd de `dockerd` documentatie en de distributiegids. *** ## 8. Herken je deze 'déjà vu'? Dan is het tijd om over te stappen {#sec-e2c8a9ca03d5} Je hoeft geen expert te zijn in complexe infrastructuur. Als je onlangs een van de onderstaande ervaringen hebt gehad, is het nu het perfecte moment om `daemon.json` aan te pakken. * **Elke keer dat je een nieuw project start, blader je door `docker-compose.yml` en kopieer/plak je loginstellingen:** Als je steeds de `max-size` en `max-file` instellingen van gisteren's code opzoekt en opnieuw plakt, verspil je kostbare tijd. Door dit één keer globaal in te stellen, starten alle containers automatisch in een 'dieetmodus'. * **Containers die op kantoor prima werkten, verliezen hun internetverbinding in een café- of VPN-omgeving:** Dit is een klassiek geval van "op mijn lokale machine werkte het wel!". Als je wilt dat je containers consistent communiceren met de buitenwereld, ongeacht de netwerkomgeving, zonder afhankelijk te zijn van de DNS-instellingen van de host, dan is een globale DNS-fix de oplossing. * **Je bent in de war door het handmatig aanpassen van de instellingen van talloze servernodes:** Ben je aan het worstelen met 'spookbugs' die ontstaan door subtiele verschillen in Docker-instellingen per server? Door slechts één `daemon.json`-bestand uit te rollen, werken alle servers volgens dezelfde regels. *** > Het moment dat je genoeg hebt van herhaalde configuraties, of moe bent van het worstelen met veranderende omgevingen, is het ideale moment om deze instellingen te implementeren. ## Samenvatting {#sec-857c80428df3} * De globale standaardwaarden van Docker worden beheerd in **`daemon.json`**. * De locatie is meestal `/etc/docker/daemon.json` * Voorbeelden van typische globale instellingen: * DNS: `"dns": ["1.1.1.1", "8.8.8.8"]` * Log driver: `"log-driver": "json-file"`, `"log-opts": {...}` * Proxy, insecure registry, standaard netwerkbereik, storage driver… * Globale instellingen zijn handig voor het voorkomen van herhaalde configuraties en bij het uitrollen van veel nodes in diverse omgevingen. Als je steeds dezelfde opties gebruikt in `docker-compose.yml` of `docker run`, dan is het misschien **tijd om ze eens naar `daemon.json` te verplaatsen**. ![Afbeelding van de Docker daemon JSON-instelling](https://blog.mikihands.com/media/editor_temp/6/00f7dbc8-f71e-485b-b9a9-e9514af1ba73.png)