Docker Daemon Configuration
The Docker daemon (dockerd) controls how all containers behave on a host. Its settings determine log rotation, network addressing, container isolation, and what happens during daemon restarts. Configuring it intentionally -- instead of relying on defaults -- prevents the most common operational issues.
Where Configuration Lives
The daemon reads its configuration from:
/etc/docker/daemon.json
This file may not exist after a fresh install. If it does not exist, create it. The daemon uses built-in defaults for any setting not specified in this file.
Recommended Baseline Configuration
Start with this minimal production configuration:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true,
"icc": false
}
This gives you:
- Log rotation that prevents disk exhaustion
- Live restore so containers keep running during daemon restarts
- Disabled inter-container communication on the default bridge network for better isolation
Settings Reference
Log Rotation (log-driver and log-opts)
By default, Docker stores container logs as JSON files with no size limit. On a busy server, this will eventually fill the disk and cause the host to become unresponsive.
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
This keeps a maximum of 3 log files per container, each capped at 10 MB (30 MB total per container). This applies to all new containers. Existing containers keep their current log configuration until they are recreated.
Live Restore (live-restore)
{
"live-restore": true
}
When live-restore is enabled, running containers continue running even when the Docker daemon is stopped or restarted. Without it, stopping the daemon kills all containers.
This is critical for production servers where you need to upgrade Docker without taking down every service. Note that some features (like Swarm mode) are not compatible with live-restore.
Inter-Container Communication (icc)
{
"icc": false
}
By default, any container on the default bridge network can communicate with any other container on the same network. Setting icc to false blocks this traffic unless containers are explicitly linked or placed on user-defined networks.
This improves isolation for hosts running unrelated containers. If you use Docker Compose (which creates its own networks per project), this setting has minimal impact on your workflows.
DNS Configuration (dns)
{
"dns": ["1.1.1.1", "8.8.8.8"]
}
Sets the DNS servers that containers use for name resolution. This is useful when the host's default resolver is unreliable or when you want containers to use specific internal DNS servers.
Custom Network Address Pools (default-address-pools)
{
"default-address-pools": [
{
"base": "172.30.0.0/16",
"size": 24
}
]
}
Docker automatically assigns IP ranges to networks. If the default ranges (172.17.x.x, 172.18.x.x, etc.) collide with your existing infrastructure (VPN ranges, corporate subnets), use this setting to define non-conflicting ranges.
Data Root (data-root)
{
"data-root": "/mnt/docker-data"
}
Changes where Docker stores all its data (images, containers, volumes). The default is /var/lib/docker. Use this if your root filesystem is small and you have a larger mounted disk available.
Changing data-root on an existing installation makes all previously stored images, containers, and volumes invisible to Docker. Either migrate the data first (rsync the old directory to the new location) or plan for a clean start.
iptables
{
"iptables": true
}
Docker manages iptables rules automatically to handle port publishing and container networking. Setting this to false disables that behavior, which means you must manage all container networking rules yourself. Only disable this if you have a specific firewall management strategy that conflicts with Docker's rules.
Insecure Registries (insecure-registries)
{
"insecure-registries": ["registry.internal.example.com:5000"]
}
Allows Docker to communicate with a registry over HTTP instead of HTTPS. Only use this for internal registries in development environments where TLS is not configured.
Expanded Production Example
Here is a more complete configuration for a production server:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true,
"icc": false,
"dns": ["1.1.1.1", "8.8.8.8"],
"default-address-pools": [
{
"base": "172.30.0.0/16",
"size": 24
}
]
}
Only include settings you actually need. Every non-default setting is a maintenance obligation.
How to Apply Changes Safely
Step 1: Back Up the Current Configuration
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak.$(date +%Y%m%d%H%M%S)
Step 2: Edit the File
sudo nano /etc/docker/daemon.json
Step 3: Validate the JSON Syntax
Invalid JSON is the most common cause of daemon startup failures after a config change. Validate before restarting:
python3 -c "import json; json.load(open('/etc/docker/daemon.json'))"
If this command produces no output, the JSON is valid. If it prints an error, fix the syntax before proceeding.
Step 4: Restart the Daemon
sudo systemctl restart docker
sudo systemctl status docker
Step 5: Verify
docker info
docker ps
docker run --rm busybox nslookup example.com
Confirm that:
- The daemon is running
- Existing containers are still healthy (if
live-restoreis enabled) - DNS resolution works inside containers
Recovering from a Bad Configuration
If the daemon fails to start after a config change:
# Check the error
sudo journalctl -u docker --no-pager -n 50
# Restore the backup
sudo cp /etc/docker/daemon.json.bak.* /etc/docker/daemon.json
# Restart
sudo systemctl restart docker
Common causes of startup failure:
- Invalid JSON (missing comma, trailing comma, unquoted key)
- Unsupported configuration key (typo in key name)
- Conflicting settings (e.g., setting
data-rootto a path that does not exist)
Key Takeaways
- Always configure log rotation -- the default (no limit) will fill your disk.
- Enable
live-restoreon production servers so containers survive daemon restarts. - Set
icc: falseto prevent unrelated containers from communicating on the default bridge. - Always back up and validate JSON before restarting the daemon.
- Keep your configuration minimal -- only set what you need.
What's Next
- Continue to Upgrade and Version Management to learn how to upgrade Docker safely.