## Unifying Team Development Environments with [[Docker]] Daemon Global Configuration {#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. * Always setting DNS to `1.1.1.1`, `8.8.8.8` * Fixing the log driver to `json-file` + `max-size=10m` * Proxy settings, 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 you extract them. This is precisely the role of **Docker daemon global configuration (`daemon.json`)**. Below, we'll cover: * Which file * Where to create it * How to write it * In what situations it's useful for developers and teams
## 1. Two Ways to Configure the Docker Daemon {#sec-9c4e8fa25a41} There are two primary ways to configure the Docker daemon (`dockerd`): 1. **Using a JSON configuration file (`daemon.json`)** ← *Recommended* 2. Passing options via **CLI flags** when running `dockerd` While you can mix and match them, **if you specify the same option in both, the daemon will fail to start.** For example, if you include a log driver in both the `--log-driver` flag and `daemon.json`, Docker will throw an error and shut down during startup. For standardizing team/server environments, it's generally recommended to: > "Consolidate as much as possible into `daemon.json`, and use flags minimally." ## 2. `daemon.json` Location Overview {#sec-97a08839a2de} The file is located at **`/etc/docker/daemon.json`**. This is for Linux, of course. While some may use Docker in environments other than Linux, I primarily use it on Linux, so I'm not as familiar with other OSes. However, here's a table summarizing the default locations for various operating systems: | Environment | Default Path | Notes | | --- | ----- | --- | | Linux (Standard Installation) | `/etc/docker/daemon.json` | Most common case | | Linux (Docker installed via 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 **may not exist by default, so if it's missing, you can create it** and start using it. ## 3. Basic Usage Pattern: "Create File → Restart Daemon" {#sec-875278239b12} For Linux, the typical workflow is as follows: 1. **Create/Edit `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. **Validate** the configuration file beforehand ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # If "configuration OK" appears, it's normal ``` 1. **Restart** the Docker daemon ```bash sudo systemctl restart docker ``` From now on, any new containers started will **inherit these global settings as defaults**, unless otherwise specified. ## 4. Key Configuration: Setting a Global DNS Server {#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 usually because they **depend on the host's DNS settings/environment**. For example: * Your entire team wants to use Cloudflare DNS (`1.1.1.1`) * There are endpoints accessible only through your company's internal DNS server In such cases, it's far more convenient to standardize DNS at the Docker daemon level rather than **adding `dns:` to `docker-compose.yml` for every project**. ### 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` file, simply add the `"dns": [...]` entry inside the root `{ ... }`. > ⚠️ **Note:** DNS settings are reflected in `/etc/resolv.conf` inside the container. They are not immediately applied to already running containers; they **take effect for newly launched containers**. ## 5. Key Configuration 2 – Global Logging Driver & Options {#sec-fe09c43b83b1} Container logs are typically stored via the `json-file` driver under `/var/lib/docker/containers/...`. 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 "just use `json-file`, but set up 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 is capped at `10MB` * A maximum of `5` files are maintained * Excess files are automatically deleted. ### 5.2 Centralized Log Collection Drivers (fluentd, journald, etc.) {#sec-e7499afd6f5d} Platform or infrastructure teams often want 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 are automatically sent to Fluentd without needing a separate `docker run --log-driver=...` command. Personally, I'm 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, enabling unified querying, filtering, and retention policies using `journalctl`. If you want to use `journald` as a global log driver, you could configure it like this, for example: ```json { "log-driver": "journald", "log-opts": { "tag": "{{.Name}}" } } ``` Here, since `tag` is set to the container name: * You can quickly **scan real-time logs** using `journalctl -f | grep {container_name}` * You can combine it with options like `--since "10m ago"` to **view logs from a specific time onward** * You can use the `-t` option (based on tag/identifier) like `journalctl -f -t {container_name}` to **specifically target logs from a particular container**. Of course, it's also possible to view logs by unit, such as `journalctl -u docker.service`, but 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." * Specifying `logging:` (Compose) or `--log-driver`, `--log-opt` (CLI) for individual containers will **override these settings for that specific container**. Strategically: * Common values go into `daemon.json` * Only special services get individual overrides This configuration is recommended. *** ## 6. Key Configuration 3 – Global Network Settings like Proxy, Insecure Registry {#sec-bc2f973bcb11} There are other frequently used options in global configuration. ### 6.1 Proxy Settings {#sec-753696ea7a1f} If you can only access external networks through a corporate proxy, you can **configure the proxy at the daemon level** instead of adding environment variables every time. ```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 ensures that the Docker daemon follows these proxy settings when pulling images or using the network during builds. ### 6.2 Insecure Registry {#sec-fe7d1c14ce8d} If you absolutely must use a registry without TLS (e.g., for internal development): ```json { "insecure-registries": ["my-registry.local:5000"] } ``` Be aware that this can be a security risk, so it should **only be used in internal test environments**. *** ## 7. Key Configuration 4 – Default Network Range, Storage Driver, etc. {#sec-efc333459aa9} ### 7.1 Customizing the Default Bridge Network Range {#sec-00d891d2b55d} If you want to avoid IP conflicts with your VPN or internal network: ```json { "default-address-pools": [ { "base": "10.20.0.0/16", "size": 24 } ] } ``` This will make Docker use 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 only use `overlay2`: ```json { "storage-driver": "overlay2" } ``` > The actual supported storage drivers depend on the OS/kernel, so always check the `dockerd` documentation and your distribution's guide. *** Understood. Focusing on "who" (persona) often makes the text stiff and sound like generic AI. I've tried to rewrite it with a focus on human experience and "frustrating situations" to resonate more with readers. *** ## 8. If You're Experiencing This 'Déjà Vu', It's Time to Adopt This {#sec-e2c8a9ca03d5} You don't need to be an infrastructure expert. If you've recently experienced any of the following, now is the time to tweak your `daemon.json`: * **Repeatedly copying and pasting log settings into `docker-compose.yml` every time you start a new project:** If you're constantly digging through yesterday's code to find `max-size` and `max-file` settings just to paste them again, you're already wasting valuable time. Set them globally just once, and all your containers will automatically start in 'diet' mode. * **Containers that worked perfectly in the office suddenly lose internet connectivity in a cafe or VPN environment:** This is a classic "it worked on my machine!" scenario. If you want your containers to consistently communicate with the outside world, regardless of network environment, without being swayed by the host's DNS settings, then global DNS pinning is the answer. * **Feeling overwhelmed trying to match settings across numerous server nodes:** Are you troubleshooting 'ghost bugs' caused by subtle differences in Docker settings between servers? Deploying a single `daemon.json` file ensures all your servers operate under the same rules. *** > When repetitive configurations become tiresome, or you're fed up with troubleshooting due to environmental changes, that's the perfect moment to adopt these settings. ## Summary {#sec-857c80428df3} * Docker's global defaults are managed in **`daemon.json`**. * The location is usually `/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, etc. * Global settings are useful for repetitive configurations and when deploying many nodes in diverse environments. If you're constantly writing the same options in `docker-compose.yml` or `docker run`, **it might be time to move them up to `daemon.json`**. ![image of docker daemon json setting](https://blog.mikihands.com/media/editor_temp/6/00f7dbc8-f71e-485b-b9a9-e9514af1ba73.png)