## [[Docker]] Daemon Global Configuration to Unify Team Development Environments {#sec-b2e039a7f45a} Whether you're using Docker locally or on a server, you often find yourself repeatedly copying and pasting the same configurations into `docker-compose.yml` for every project. * Consistently setting DNS to `1.1.1.1`, `8.8.8.8`, * Fixing the log driver to `json-file` + `max-size=10m`, * Or configurations for proxies, insecure registries, default network ranges, and more. These aren't **individual container settings but rather “host-wide defaults”**, which are much easier to manage if centralized. This is precisely the role of **Docker daemon global configuration (`daemon.json`)**. Below, we'll cover: * Which file to create * Where to create it * How to write it * And in what situations it proves useful for developers and teams.
## 1. Two Ways to Configure the Docker Daemon \{\#sec\-7390246eab38\} {#sec-9c4e8fa25a41} The Docker daemon (`dockerd`) can be configured primarily in two ways: 1. **Using a JSON configuration file (`daemon.json`)** ← *Recommended* 2. Passing options via **CLI flags** when running `dockerd` While you can combine both methods, **specifying the same option in both will prevent the daemon from starting at all.** For example, if you include a log driver in both the `--log-driver` flag and `daemon.json`, Docker will error out and terminate during startup. For unifying team/server environments, it's generally recommended to: > “Consolidate as much as possible into `daemon.json`, and use flags minimally.” ## 2. `daemon.json` Location {#sec-97a08839a2de} The file is located at **`/etc/docker/daemon.json`**. This is for Linux, of course. While some might use Docker in non-Linux environments, I primarily work with Linux, so I'm less familiar with other OSes. However, here's a convenient table summarizing the default locations per OS: | Environment | Default Path | Notes | | --- | ----- | --- | | Linux (standard installation) | `/etc/docker/daemon.json` | Most common case | | Linux (Docker installed with snap) | `/var/snap/docker/current/config/daemon.json` | Ubuntu snap package | | Windows Server / Docker Engine | `C:\ProgramData\Docker\config\daemon.json` | | | Docker Desktop (Mac / Windows) | `~/.docker/daemon.json` | | * This file **might not exist by default, so if it's missing, you can create it yourself**. ## 3. Basic Usage Pattern: “Create File → Restart Daemon” \{\#sec\-bffe465cc36f\} {#sec-875278239b12} On Linux, the typical workflow is as follows: 1. **Write/Modify `daemon.json`** ```json { "dns": ["1.1.1.1", "8.8.8.8"], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } ``` 1. **Pre-validate** the configuration file ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # If 'configuration OK' appears, it's valid :contentReference[oaicite:7]{index=7} ``` 1. **Restart** Docker daemon ```bash sudo systemctl restart docker ``` From now on, newly launched containers will **inherit these global settings as defaults** unless specified otherwise. ## 4. Key Setting: Globally Pinning DNS Servers \{\#sec\-d9c2238a423f\} {#sec-c284419e45cd} ### 4.1 Why Global DNS? {#sec-78011cf35f17} If you frequently encounter issues like containers “strangely failing to find external APIs” or “internal domains not resolving,” it's often because they **rely on the host's DNS settings/environment**. For instance: * Your entire team wants to use Cloudflare DNS (`1.1.1.1`) * There's an endpoint only accessible via your company's internal DNS server In such cases, **rather than adding `dns:` to `docker-compose.yml` for every project**, it's far more convenient to unify it at the Docker daemon level. ### 4.2 Configuration Example (`daemon.json`) {#sec-2a85a418cbea} ```json { "dns": ["1.1.1.1", "8.8.8.8"] } ``` If you already have a `daemon.json`, simply add the `"dns": [...]` entry within the root `{ ... }`. > ⚠️ **Caution:** DNS settings are reflected in `/etc/resolv.conf` inside the container. They are not applied immediately to already running containers, but **only to newly launched ones**. ## 5. Key Setting 2 – Global Logging Driver & Options Configuration \{\#sec\-360ddebc7b6c\} {#sec-fe09c43b83b1} Container logs are typically stored under `/var/lib/docker/containers/...` via the `json-file` driver. Changing this globally allows you to: * Log format * Log storage location * Log rotation policy To **apply these uniformly across all containers**. ### 5.1 Default `json-file` Driver + Rotation {#sec-26c5fb9056b5} The most common pattern is to “simply use `json-file`, but configure rotation to prevent disk overflow.” ```json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } } ``` With this setup: * Each container's log file size will be a maximum of `10MB`. * A maximum of `5` files will be retained. * Excess files will be automatically deleted. ### 5.2 Centralized Log Collection Drivers (fluentd, journald, etc.) {#sec-e7499afd6f5d} For platform or infrastructure teams, there's often a need to send all container logs to a **centralized logging system**. For example, if using Fluentd: ```json { "log-driver": "fluentd", "log-opts": { "fluentd-address": "localhost:24224", "tag": "{{.Name}}" } } ``` With this configuration, all container logs will be automatically sent to Fluentd without needing a separate `docker run --log-driver=...` command. Personally, I'm also quite fond of the **`journald` driver**. In a systemd-based Linux environment, it allows you to consolidate both application logs and Docker container logs into a single `journald` instance, unifying viewing, filtering, and retention policies using just `journalctl`. If you wish to use `journald` as your global log driver, you can configure it like this, for example: ```json { "log-driver": "journald", "log-opts": { "tag": "{{.Name}}" } } ``` Since `tag` is used as the container name here: * You can **quickly review real-time logs** using `journalctl -f | grep {container_name}`. * You can also combine it with options like `--since "10m ago"` to **view logs only after a specific time**. * Or, using the `-t` option (based on tag/identifier) like `journalctl -f -t {container_name}`, you can **specifically pinpoint logs for a particular container**. While it's also possible to view logs by unit, like `journalctl -u docker.service`, filtering by container name is more intuitive and requires less typing, making it much more frequently used in practice. ### 5.3 Relationship with Compose / `docker run` {#sec-8d284e8a0dfd} * **Global `log-driver` + `log-opts`** act as “defaults” * If `logging:` (Compose) or `--log-driver`, `--log-opt` (CLI) are specified for individual containers, **only that container will override** the global settings. Strategically, we recommend a configuration where: * Common values are in `daemon.json`. * Only specific services are overridden individually. *** ## 6. Key Setting 3 – Global Network Configurations like Proxy, Insecure Registry \{\#sec\-0d687ac65460\} {#sec-bc2f973bcb11} There are other frequently used options in global settings. ### 6.1 Proxy Settings {#sec-753696ea7a1f} If you can only access external networks via a corporate proxy, instead of setting environment variables every time, you can **configure the proxy at the daemon level**. ```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" } } ``` This way, the Docker daemon will follow these proxy settings when pulling images or using the network during builds. ### 6.2 Insecure Registry {#sec-fe7d1c14ce8d} If you absolutely need to use a registry without TLS (e.g., for internal development): ```json { "insecure-registries": ["my-registry.local:5000"] } ``` This can be a security risk, so be careful to use it **only in internal testing environments**. *** ## 7. Key Setting 4 – Default Network Range, Storage Driver, and More \{\#sec\-3598d5fb02d3\} {#sec-efc333459aa9} Some more infrastructure-oriented options: ### 7.1 Customizing the Default Bridge Network Range {#sec-00d891d2b55d} When you want to avoid IP conflicts with VPNs or internal company networks: ```json { "default-address-pools": [ { "base": "10.20.0.0/16", "size": 24 } ] } ``` This ensures Docker uses the `10.20.x.0/24` range when creating new bridge networks. ### 7.2 Forcing a Storage Driver {#sec-04d867ec1442} The default storage driver can vary depending on the Linux distribution. If your team has decided to use only `overlay2`: ```json { "storage-driver": "overlay2" } ``` > The actual supported storage drivers vary by OS/kernel, so always consult the `dockerd` documentation and your distribution's guide. *** ## 8. If You're Experiencing This 'Deja Vu', It's Time to Adopt Global Settings \{\#sec\-807a100451aa\} {#sec-e2c8a9ca03d5} You don't need to be an infrastructure expert. If you've recently experienced any of the following, it's high time you started configuring `daemon.json`. * **You're digging through `docker-compose.yml` and copy-pasting log settings every time you start a new project:** If you're constantly fetching `max-size` and `max-file` settings from old code and pasting them in again, you're already wasting valuable time. Set it globally once, and all your containers will automatically start in 'diet' mode. * **Containers that worked perfectly in the office suddenly lose internet connection in a cafe or VPN environment:** This is a classic "but it worked on my machine!" scenario. If you want your containers to communicate consistently with the outside world in any network environment, without being swayed by the host's DNS settings, then global DNS pinning is the answer. * **You're losing your mind trying to manually adjust settings on countless server nodes:** Are you debugging "ghost bugs" caused by subtly different Docker configurations on each server? Deploying a single `daemon.json` file can make all your servers behave like a disciplined army, following the exact same rules. *** > The optimal moment to adopt these settings is when you're tired of repetitive configurations or fed up with debugging issues caused by environmental changes. ## Summary {#sec-857c80428df3} * Docker's global defaults are managed in **`daemon.json`**. * The location is typically `/etc/docker/daemon.json`. * Examples of common global settings: * DNS: `"dns": ["1.1.1.1", "8.8.8.8"]` * Log driver: `"log-driver": "json-file"`, `"log-opts": {...}` * Proxy, insecure registry, default network range, storage driver… * Global settings are useful for repetitive configurations and when deploying many nodes across diverse environments. If you're constantly using the same options in `docker-compose.yml` or `docker run`, **it might be time to elevate them to `daemon.json`**. ![image of docker daemon json setting](https://blog.mikihands.com/media/editor_temp/6/00f7dbc8-f71e-485b-b9a9-e9514af1ba73.png)