## 通过 [[Docker]] 守护进程全局配置,统一团队开发环境 {#sec-b2e039a7f45a} 无论是在本地还是服务器上使用 Docker,我们经常会发现自己需要在每个项目的 `docker-compose.yml` 文件中重复粘贴相同的配置。 * 例如,总是将 DNS 设置为 `1.1.1.1`、`8.8.8.8` * 或者将日志驱动程序固定为 `json-file` + `max-size=10m` * 还有代理、不安全注册表、默认网络范围等… 这些配置与其作为**容器的单独设置**,不如将其提取为**“主机整体默认值”**,这样管理起来会方便得多。而承担这一角色的正是 **Docker 守护进程的全局配置(`daemon.json`)**。 接下来,我们将整理以下内容: * 需要创建什么文件 * 文件应该放在哪里 * 如何编写配置 * 以及在什么情况下,它对哪些开发者/团队会更有用
## 1. 两种 Docker 守护进程配置方式 {#sec-9c4e4fa25a41} Docker 守护进程(`dockerd`)主要可以通过两种方式进行配置: 1. **使用 JSON 配置文件(`daemon.json`)** ← *推荐* 2. 在运行 `dockerd` 时,通过 **CLI 标志**传递选项 尽管两者可以混合使用,但**如果在两者中都指定了相同的选项,守护进程将无法启动。** 例如,如果 `--log-driver` 标志和 `daemon.json` 都设置了日志驱动程序,Docker 会在启动阶段报错并退出。 为了统一团队/服务器环境,通常建议: > “尽可能将所有配置集中在 `daemon.json` 中,仅使用最少的标志。” ## 2. `daemon.json` 文件位置 {#sec-97a08839a2de} 文件的位置通常是 **`/etc/docker/daemon.json`**。当然,这是针对 Linux 环境而言。 虽然可能有人在非 Linux 环境下使用 Docker,但我个人只在 Linux 上使用,所以对其他操作系统不太熟悉。不过,为了方便大家查看,下面将各操作系统的默认位置整理成表格: | 环境 | 默认路径 | 备注 | | --- | ----- | --- | | Linux (常规安装) | `/etc/docker/daemon.json` | 最常见的情况 | | Linux (通过 snap 安装的 Docker) | `/var/snap/docker/current/config/daemon.json` | Ubuntu snap 包 | | Windows Server / Docker Engine | `C:\ProgramData\Docker\config\daemon.json` | | | Docker Desktop (Mac / Windows) | `~/.docker/daemon.json` | | * 此文件**可能默认不存在,如果不存在,直接创建**即可使用。 ## 3. 基本使用模式:“创建文件 → 重启守护进程” {#sec-875278239b12} 以 Linux 为例,常见的工作流程如下: 1. **编写/修改 `daemon.json`** ```json { "dns": ["1.1.1.1", "8.8.8.8"], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } ``` 2. **提前验证**配置文件是否有效 ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # 如果显示 "configuration OK",则表示正常 ``` 3. **重启** Docker 守护进程 ```bash sudo systemctl restart docker ``` 从现在开始,新启动的容器,除非有特殊配置,否则都将**继承**这些全局设置作为**默认值**。 ## 4. 主要配置:全局固定 DNS 服务器 {#sec-c284419e45cd} ### 4.1 为什么要全局配置 DNS? {#sec-78011cf35f17} 如果你的容器经常遇到“无法解析外部 API”或“内部域名无法解析”等奇怪问题,那很可能是因为它们**依赖于主机的 DNS 设置/环境**。 例如: * 整个团队都希望使用 Cloudflare DNS(`1.1.1.1`) * 有些端点只能通过公司内部 DNS 服务器访问 在这种情况下,**与其在每个项目的 `docker-compose.yml` 中添加 `dns:`**,不如直接在 Docker 守护进程层面进行统一配置,这样会方便得多。 ### 4.2 配置示例 (daemon.json) {#sec-2a85a418cbea} ```json { "dns": ["1.1.1.1", "8.8.8.8"] } ``` 如果已存在 `daemon.json`,只需在根 `{ ... }` 中添加 `"dns": [...]` 条目即可。 > ⚠️ **注意:** DNS 设置将反映在容器内的 `/etc/resolv.conf` 中。它不会立即应用于已运行的容器,而是**从新启动的容器开始生效**。 ## 5. 主要配置 2 – 全局设置日志驱动程序及选项 {#sec-fe09c43b83b1} 容器日志默认通过 `json-file` 驱动程序存储在 `/var/lib/docker/containers/...` 目录下。如果在全局层面进行更改,可以实现: * 日志格式 * 日志存储位置 * 日志轮转策略 这些都将**统一应用于所有容器**。 ### 5.1 默认 json-file 驱动程序 + 轮转 {#sec-26c5fb9056b5} 最常见的模式是“使用 `json-file`,但配置日志轮转以防止磁盘空间耗尽”。 ```json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" } } ``` 这样设置后,每个容器的日志文件大小将限制在 `10MB`,最多保留 `5` 个文件,超出部分将自动删除。 ### 5.2 用于中央日志收集的驱动程序 (fluentd, journald 等) {#sec-e7499afd6f5d} 对于平台团队/基础设施团队来说,通常会希望将所有容器的日志发送到**中央日志系统**。 例如,如果使用 Fluentd: ```json { "log-driver": "fluentd", "log-opts": { "fluentd-address": "localhost:24224", "tag": "{{.Name}}" } } ``` 这样设置后,无需额外的 `docker run --log-driver=...` 命令,所有容器的日志都将自动发送到 Fluentd。 我个人也相当喜欢 **`journald` 驱动程序**。在基于 systemd 的 Linux 环境中,它可以将应用程序日志和 Docker 容器日志都收集到 journald 中,从而可以通过 `journalctl` 统一查询、过滤和管理日志保留策略。 如果想将 `journald` 用作全局日志驱动程序,可以这样配置: ```json { "log-driver": "journald", "log-opts": { "tag": "{{.Name}}" } } ``` 由于这里将 `tag` 设置为容器名称,因此: * 可以通过 `journalctl -f | grep {container_name}` 快速**实时查看日志** * 结合 `--since "10m ago"` 等选项,可以**只查看特定时间点之后的日志** * 使用 `-t` 选项(基于标签/标识符),例如 `journalctl -f -t {container_name}`,可以**精确地只查看特定容器的日志** 当然,也可以像 `journalctl -u docker.service` 那样按单元查看,但根据容器名称进行过滤更直观,输入也更少,因此在实际工作中会更常用。 ### 5.3 与 Compose / `docker run` 的关系 {#sec-8d284e8a0dfd} * **全局 `log-driver` + `log-opts`** 扮演“默认值”的角色 * 如果在单个容器中指定 `logging:` (Compose) 或 `--log-driver`、`--log-opt` (CLI),则**仅覆盖该容器的设置** 从策略上讲,我们推荐将公共配置放入 `daemon.json`,而只对特殊服务进行单独覆盖的配置方式。 *** ## 6. 主要配置 3 – 代理、不安全注册表等全局网络设置 {#sec-bc2f973bcb11} 全局配置中还有一些常用的选项。 ### 6.1 代理设置 {#sec-753696ea7a1f} 如果只能通过公司内部代理访问外部网络,与其每次都添加环境变量,不如**在守护进程层面配置代理**。 ```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" } } ``` 这样,Docker 守护进程在拉取镜像或构建时使用网络时,都会遵循这些代理设置。 ### 6.2 不安全注册表 {#sec-fe7d1c14ce8d} 如果必须使用没有 TLS 的注册表(例如内部开发用途): ```json { "insecure-registries": ["my-registry.local:5000"] } ``` 这可能存在安全风险,因此请务必注意**仅在内部测试环境中使用**。 *** ## 7. 主要配置 4 – 默认网络范围、存储驱动程序等 {#sec-efc333459aa9} ### 7.1 自定义默认 bridge 网络范围 {#sec-00d891d2b55d} 当您希望避免与 VPN 或公司内部网络 IP 冲突时: ```json { "default-address-pools": [ { "base": "10.20.0.0/16", "size": 24 } ] } ``` 这样,Docker 在创建新的 bridge 网络时将使用 `10.20.x.0/24` 网段。 ### 7.2 强制存储驱动程序 {#sec-04d867ec1442} 根据 Linux 发行版的不同,默认存储驱动程序可能会有所差异。如果团队决定只使用 `overlay2`: ```json { "storage-driver": "overlay2" } ``` > 实际支持的存储驱动程序因操作系统/内核而异,因此务必查阅 `dockerd` 文档和发行版指南。 *** ## 8. 如果你正经历“似曾相识”的困扰,请尝试引入它 {#sec-e2c8a9ca03d5} 即便你不了解复杂的底层基础设施,也没关系。如果你最近有过以下经历,那么现在正是你该调整 `daemon.json` 的时候了。 * **每次启动新项目时,你都在 `docker-compose.yml` 中翻来覆去地复制粘贴日志配置:** 如果你还在从昨天写的代码里寻找 `max-size`、`max-file` 设置并再次粘贴,那么你已经在浪费宝贵的时间了。只要全局配置一次,所有容器都会自动以“精简模式”启动。 * **在办公室运行正常的容器,一到咖啡馆或 VPN 环境就断网:** 这就是典型的“在我本地明明可以”的案例。如果你想让你的容器在任何网络环境下都能稳定地与外部通信,而不受主机 DNS 设置的影响,那么全局固定 DNS 就是正确的解决方案。 * **为众多服务器节点逐一配置,让你头昏脑胀:** 你是否因为每台服务器的 Docker 配置细微差异而产生的“幽灵 bug”而苦恼?只需部署一个 `daemon.json` 文件,所有服务器都将按照相同的规则运行。 *** > 当你厌倦了重复的配置,或者受够了因环境变化而带来的反复折腾时,正是引入此设置的最佳时机。 ## 总结 {#sec-857c80428df3} * Docker 的全局默认值通过 **`daemon.json`** 进行管理。 * 位置通常在 `/etc/docker/daemon.json` * 典型的全局配置示例: * DNS: `"dns": ["1.1.1.1", "8.8.8.8"]` * 日志驱动程序: `"log-driver": "json-file"`, `"log-opts": {...}` * 代理、不安全注册表、默认网络范围、存储驱动程序… * 全局设置在处理重复配置以及在不同环境中部署大量节点时非常有用。 如果你还在 `docker-compose.yml` 或 `docker run` 命令中重复使用相同的选项,那么**现在也许是时候将它们提升到 `daemon.json` 中了**。 ![Docker 守护进程 json 设置图示](https://blog.mikihands.com/media/editor_temp/6/00f7dbc8-f71e-485b-9a9-e9514af1ba73.png)