daemon.json file is one of the highest-leverage Docker files in production. A few keys can improve container reliability, host safety, and observability. In this post, we review a real-world configuration and explain what each setting does, why it matters, and what to validate before rollout.Disclaimer#
This configuration is a strong starting point for many production environments, but it is not a one-size-fits-all solution. Always test changes in staging and monitor closely after deployment. The best settings depend on your specific workloads, security requirements, and operational practices.
Configuration Under Review#
{
"default-shm-size": "64M",
"default-ulimits": {
"nofile": {
"Hard": 65535,
"Name": "nofile",
"Soft": 65535
}
},
"dns": [
"{{ dns_primary_ip }}",
"{{ dns_secondary_ip }}"
],
"live-restore": true,
"log-driver": "local",
"log-opts": {
"compress": "true",
"max-file": "5",
"max-size": "10m"
},
"no-new-privileges": true,
"registry-mirrors": [
"{{ registry_mirror_url }}"
],
"storage-driver": "overlay2"
}{{ ... }} values indicate template placeholders (for example with Ansible, Helm-like templating, or a custom CI render step). Deploying this file without rendering those values first will lead to misconfiguration.Key-by-Key Analysis#
default-shm-size: "64M"#
Docker mounts /dev/shm as tmpfs inside containers. The default is often too small for browsers, headless tests, PostgreSQL shared memory usage, and data-heavy IPC workloads.
What this gives you:
- Predictable shared memory baseline for all containers.
- Fewer random crashes due to
No space left on devicein/dev/shm.
What to watch:
64Mmay still be too low for Chrome/Playwright, ML, or large in-memory jobs.- Prefer setting higher values per workload when needed (
--shm-size=256mor Compose equivalent).
default-ulimits.nofile = 65535#
This raises file descriptor limits for containers by default.
Why it matters:
- High-concurrency services (reverse proxies, brokers, DB clients) consume many file descriptors.
- Prevents hard-to-debug failures such as
too many open filesunder load.
Operational advice:
- Match host-level limits (
/etc/security/limits.conf, systemd service limits) to avoid a false sense of safety. - Validate under stress with realistic connection counts.
dns: ["{{ dns_primary_ip }}", "{{ dns_secondary_ip }}"]#
This forces explicit DNS resolvers for containers instead of inheriting host defaults.
Benefits:
- Stable, deterministic name resolution across environments.
- Easier troubleshooting when host DNS stacks differ.
Risks:
- If resolver IPs are unreachable, all container DNS resolution degrades.
- Hard-coding resolvers can bypass local split-DNS behavior if not planned.
Best practice:
- Use two independent resolvers.
- Add health checks and monitoring for resolver availability.
live-restore: true#
Keeps containers running during daemon upgrades/restarts (where supported).
Why it is valuable:
- Reduces app impact during Docker daemon maintenance.
- Good fit for hosts where short daemon restarts are common.
Limitations:
- Not a replacement for orchestrator-level high availability.
- Network/control-plane operations may still be temporarily impacted.
log-driver: "local" with rotation options#
"log-driver": "local",
"log-opts": {
"compress": "true",
"max-file": "5",
"max-size": "10m"
}This is a strong production default.
Why:
localis more space-efficient thanjson-filein many scenarios.- Rotation (
5 x 10m) caps per-container disk growth. - Compression reduces log storage pressure.
Trade-offs:
- Very high verbosity workloads may still require centralized logging.
- Keep an eye on total host log usage when container count grows.
no-new-privileges: true#
Prevents privilege escalation via setuid/setgid binaries and similar mechanisms in containers.
Security impact:
- Excellent baseline hardening control.
- Helps enforce least privilege behavior in container processes.
Compatibility note:
- Rare images relying on privilege elevation may break and need redesign.
registry-mirrors: ["{{ registry_mirror_url }}"]#
Configures a pull-through mirror or internal registry proxy.
Advantages:
- Faster image pulls.
- Better resilience against external registry rate limits.
- Lower internet egress and improved supply-chain control.
What to validate:
- Mirror freshness and cache policy.
- TLS trust chain and authentication to the mirror.
storage-driver: "overlay2"#
overlay2 is the recommended Linux storage driver for most modern distributions and kernels.
Strengths:
- Mature and performant for general container workloads.
- Broad compatibility with mainstream Docker installations.
Caution:
- Confirm backing filesystem compatibility and kernel support.
- Never change storage driver on a running node without migration planning.
Deployment Checklist#
- Render template placeholders before deployment.
- Validate JSON syntax.
- Apply configuration and restart Docker.
- Verify daemon settings took effect.
- Run a smoke test with representative workloads.
# 1) Render template (example path)
cat /etc/docker/daemon.json
# 2) Validate JSON syntax
jq . /etc/docker/daemon.json
# 3) Restart Docker daemon
sudo systemctl restart docker
# 4) Verify effective configuration
docker info | grep -E "Logging Driver|Cgroup|Storage Driver|Live Restore Enabled"
docker info --format '{{json .}}' | jq '.RegistryConfig.Mirrors'
# 5) Functional checks
docker run --rm busybox nslookup example.com
docker run --rm busybox sh -c 'ulimit -n'Recommended Next Improvements#
- Add centralized log shipping (Loki, Elasticsearch, OpenSearch, or a managed platform).
- Enforce image provenance and signature verification in CI/CD.
- Run containers as non-root where possible (
USERin Dockerfile). - Define daemon config as code and roll it out with canary hosts first.
- Implement monitoring and alerting for Docker daemon health and resource usage.
