Configuring the daemon
daemon.json and engine defaults.
The engine’s behaviour is configured in /etc/docker/daemon.json — the single source of truth for daemon-wide settings: where images and containers live (data-root), the default logging and storage drivers, registry mirrors and insecure registries, default resource ulimits, the default runtime, and more. It is the difference between per-container flags (this container) and engine policy (every container).
{"data-root": "/var/lib/docker","log-driver": "json-file","log-opts": { "max-size": "10m", "max-file": "3" },"registry-mirrors": ["https://mirror.acme.internal"],"default-ulimits": { "nofile": { "Name": "nofile", "Soft": 65536, "Hard": 65536 } },"live-restore": true}
Scenario: a node dies from its own logs
A host goes down not from load but from a full disk, and the culprit is a chatty container: the default json-file driver writes to disk and never rotates unless told to, so one verbose service fills /var/lib/docker over a weekend. Set max-size and max-file globally in daemon.json, or move to a driver that ships logs off-box (journald, or fluentd/syslog to a collector). Fix it before it bites, because the symptom looks like a mystery outage.
# per-container override to confirm behaviour before rolling out the daemon default$ docker run -d --log-driver json-file --log-opt max-size=5m --log-opt max-file=2 nginx:1.27$ docker inspect -f '{{.HostConfig.LogConfig}}' <id>{json-file map[max-file:2 max-size:5m]}
Scenario: an internal registry over plain HTTP
A team runs an internal registry that (for now) serves plain HTTP, and pulls fail with an HTTPS error. registry-mirrors points Docker Hub pulls at a caching mirror so an upstream outage or rate limit does not stop builds; insecure-registries tells the daemon to allow a specific non-TLS registry. Use the mirror widely; use insecure-registries sparingly and only for hosts you control, since it disables transport security for them.
{"registry-mirrors": ["https://mirror.acme.internal"],"insecure-registries": ["registry.dev.acme.internal:5000"]}# then: docker pull registry.dev.acme.internal:5000/app:1.0 (no TLS error)
Apply and validate safely
Changes take effect on daemon restart, and running containers survive it (with live-restore). The risk is a JSON typo: an invalid daemon.json stops dockerd from starting at all, and since dockerd serves the API, docker commands then fail with “cannot connect.” Validate before you restart, and keep a known-good copy.
$ sudo dockerd --validate --config-file /etc/docker/daemon.jsonconfiguration OK$ sudo systemctl restart docker$ docker info -f '{{.LoggingDriver}} | data-root {{.DockerRootDir}}'json-file | data-root /var/lib/docker