## [[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-9c4e5fa4a41} 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" } } ``` 1. **提前验证**配置文件是否有效 ```bash sudo dockerd --validate --config-file=/etc/docker/daemon.json # 如果显示 "configuration OK" 则表示正常 ``` 1. **重启** 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 设置而头晕脑胀:** 您是否因为每个服务器的 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-b9a9-e9514af1ba73.png)