为什么要修改 Docker 配置文件?
一般来说,Docker 安装完成之后,默认配置通常已经能够满足日常开发和简单部署需求。
但是到了生产环境,经常会遇到一些和业务代码本身无关的问题:
- Docker Hub 镜像拉取速度慢;
- 容器日志无限增长导致磁盘占满;
- Docker daemon 维护重启影响运行中的容器;
- Docker 数据目录持续增长占满系统盘;
- Docker 网络配置与实际环境存在冲突。
这些问题中,部分内容可以通过修改 Docker daemon 的配置提前解决。
Docker Engine 提供了一个专门用于管理配置的文件:daemon.json。
很多网上的教程、技术文章会直接给出一份几十行的配置:
复制替换,这就是 Docker 生产环境配置的最佳实践。
这种做法并不推荐!
因为 Docker 的 daemon.json 中有很多配置都依赖具体环境。
例如:
storage-driver和底层文件系统有关;dns和网络环境有关;userland-proxy和 Docker 网络实现有关;iptables会直接影响 Docker 网络;- Docker Desktop 和 Linux Docker Engine 的配置方式也不同;
- …
因此,
生产环境不是配置越多就一定越好,而是只配置真正需要的东西。
本文主要从实际部署角度,梳理 daemon.json 中比较值得关注的配置,并说明哪些配置不应该直接复制。
Docker 的 daemon.json 在哪里?
Linux Docker Engine
如果是使用 Linux Docker Engine,默认配置文件一般位于:
/etc/docker/daemon.json。
如果目录或配置文件不存在,可以执行命令创建:
# 创建目录mkdir -p /etc/docker
# 创建配置文件touch /etc/docker/daemon.json配置文件本身不存在,并不代表 Docker 安装或使用过程有问题。
daemon.json 默认就可能不存在。
Docker 在没有这个文件时,会使用 daemon 自身的默认配置运行。
因此,如果不存在 daemon.json,只是表示:
当前没有通过这个配置文件覆盖 Docker daemon 的默认配置。
Docker Engine Rootless
如果使用的是 Docker Engine Rootless 模式,则配置文件位置不同:
~/.config/docker/daemon.json
如果文件不存在,可以执行:
mkdir -p ~/.config/docker
touch ~/.config/docker/daemon.json如果设置了 XDG_CONFIG_HOME,则 Rootless Docker 会根据该环境变量确定配置目录。
自定义配置文件
Docker 也支持通过 dockerd --config-file 指定其他配置文件。
例如:
dockerd --config-file=/etc/docker/daemon.json这说明 daemon.json 并不是 Docker 唯一支持的配置文件位置。
但是对于使用系统服务管理 Docker 的生产环境,一般不建议为了修改配置而手动执行dockerd。
在使用 systemd 管理 Docker 的 Linux 生产服务器上,通常由 systemd 负责 Docker 服务的启动、停止和重启。
Docker Desktop
如果使用的是 Docker Desktop,就不能简单照搬 Linux Docker Engine 的配置方式。
macOS 和 Windows 上的 Docker Desktop 中的 daemon 实际运行在 Docker Desktop 管理的 Linux 环境中。
以 macOS Docker Desktop 为例,可以打开:
Docker Desktop→ Settings→ Docker Engine然后直接在配置界面编辑 JSON,修改完成后点击 Apply & Restart。
Docker Desktop 会重新加载配置并启动 Docker Engine。
如图所示:

本文下述配置内容,默认以:Linux Docker Engine 作为主要配置环境。
dockerd 启动参数 和 daemon.json 有什么关系?
Docker daemon 的配置主要有两种来源:
第一种:daemon.json;
第二种:dockerd 启动参数。
例如 daemon.json 中配置:
{ "debug": true}而又通过 dockerd 启动参数指定:
dockerd --debug=false那么同一个配置项就存在两处不同的配置来源。
同一个配置项如果同时通过 daemon.json 和 dockerd 启动参数指定,Docker daemon 会因为配置冲突而无法启动。
因此生产环境最好明确配置职责:
本文推荐的方式就是:
daemon.json 负责 Docker daemon 的配置;
systemd 负责 Docker 服务的启动、停止和重启。
为什么还要检查 dockerd 启动参数?
因为检查和修改是两件完全不同的事情。
修改 daemon.json 之前,可以先确认当前 Docker daemon 是如何启动的:
systemctl cat docker也可以查看正在运行的 dockerd:
ps aux | grep '[d]ockerd'这样做的目的不是让你以后同时维护两套配置,而是避免不知道当前环境已经通过启动参数配置了哪些选项。
修改 daemon.json 的推荐流程
- 备份现有配置;
- 修改
daemon.json; - 验证 JSON 和 daemon 配置;
- 重启 Docker;
- 检查 Docker 服务;
- 检查 Docker daemon;
- 检查容器;
- 检查业务。
备份现有配置:
cp /etc/docker/daemon.json /etc/docker/daemon.json.bak如果文件原本不存在,则无需备份。
修改完成后,可以先使用 dockerd --validate 验证配置:
dockerd --validate --config-file=/etc/docker/daemon.json如果配置有效,会显示配置验证成功的消息,如:configuration OK。
如果 JSON 存在语法错误,则会直接报告错误,如:
unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '}' looking for beginning of object key string具体报错内容会根据错误位置不同而变化。
生产环境真正值得配置什么?
log-driver:配置容器日志驱动。log-opts:限制容器日志大小和轮转数量。live-restore:降低 Docker daemon 重启对运行中容器的影响。data-root:将 Docker 数据放到独立磁盘或指定存储位置。registry-mirrors:在实际网络环境允许的情况下配置镜像加速。
其他配置,例如 dns、storage-driver、iptables、userland-proxy、insecure-registries 等,则应该根据实际环境决定。
容器日志配置:生产环境最值得配置的配置项之一
Docker Engine 默认日志驱动为 json-file。
可以通过:
docker info --format '{{.LoggingDriver}}'查看当前默认日志驱动。
如果返回 json-file,说明当前 Docker daemon 的默认日志驱动为 json-file,容器的标准输出和标准错误会以 JSON 日志文件形式保存。
json-file 默认不会对日志文件进行大小限制和自动轮转。
如果一个服务持续输出大量日志,日志文件会不断增长,最终可能导致磁盘空间不足。
因此生产环境非常值得设置日志轮转策略。
最常见的配置为:
{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }}其中,
max-size 表示单个日志文件达到指定大小后进行轮转。
max-file 表示日志轮转时最多保留的日志文件数量。
一个非常容易踩坑的问题就是:
修改 daemon.json 中的 log-driver 和 log-opts,并不会自动修改已经存在的容器。
如果原有容器已经运行,之后再修改 daemon.json,已经创建并启动的容器并不会因为 Docker daemon 重启就自动重新应用新的日志配置。
Docker Compose 环境需要重新创建相关容器,例如:
docker compose up -d --force-recreate但生产环境不要机械执行,应结合服务是否有状态、是否允许重建以及维护窗口决定。
如果服务涉及数据库、持久化数据或者其他有状态组件,应当先确认数据卷、停机策略和业务影响。
live-restore:减少 daemon 重启对容器的影响
Docker daemon 需要升级、修改配置或进行维护时,通常需要重启 Docker。
Docker daemon 重启时,默认情况下 Docker 对运行中容器的管理能力可能会暂时受到影响。
可以考虑添加配置:
{ "live-restore": true}修改 daemon.json 并启用 live-restore 后,需要重启 Docker daemon 才会生效。
live-restore 可以在 Docker daemon 重启期间尽可能保持运行中容器继续运行,从而降低 daemon 维护对业务的影响。
但它不能解决主机重启、容器运行时故障等问题。
Docker 数据目录:不要让系统盘默默被吃光
Docker 默认会把镜像、容器、容器可写层以及部分 Docker 管理的数据存放在 Docker 数据目录中。
Linux 环境中通常可以通过:
# 查看所有信息docker info
# 仅查看数据存储目录docker info --format '{{.DockerRootDir}}'查看存放目录。
例如:Docker Root Dir: /var/lib/docker。
如果系统盘只有几十 GB,而服务器运行大量容器、镜像或者构建任务,/var/lib/docker 很容易不断增长。
因此对于磁盘空间比较紧张或者 Docker 负载较大的生产服务器,可以考虑将 Docker 数据目录放到独立磁盘。
常见做法是:
- 修改之前停止 Docker 并创建目标目录。
systemctl stop docker
mkdir -p /data/docker/- 把 Docker 的数据目录
/var/lib/docker/复制到/data/docker/。
# 复制数据rsync -aHAX /var/lib/docker/ /data/docker/其中:
-a:归档模式,保留文件权限、时间等属性;-H:保留硬链接;-A:保留 ACL 权限;-X:保留扩展属性。
- 然后确认数据完整后,再修改
daemon.json。
{ "data-root": "/data/docker"}- 启动 Docker:
systemctl start docker- 最后检查存储路径是否已经修改完成:
docker info确认输出结果是否已变更为用户自定义目录,如:
Docker Root Dir: /data/docker- 确认 Docker 已经正常使用新的数据目录,并验证容器、镜像和数据卷均正常后,再考虑清理旧的
/var/lib/docker,不要在迁移完成后立即删除旧目录。
需要特别注意:
data-root 不是简单地“换一个目录”这么简单。
如果服务器已经运行生产业务,原来的镜像、容器以及 Docker 管理的数据仍然位于旧目录,
直接修改配置而不迁移数据,会让 Docker 看不到原来的数据。
所以:
新服务器还没有业务时,配置 data-root 很简单;
已经运行生产业务的服务器修改 data-root,则应该按照迁移流程执行。
registry-mirrors:镜像拉取速度慢时再配置
如果服务器访问 Docker Hub 较慢,可以考虑配置 registry-mirrors。
例如:
{ "registry-mirrors": [ "https://docker.rainbond.cc", "https://docker.1ms.run", "https://docker.m.daocloud.io" ]}不建议直接复制网上公开的第三方镜像加速地址。 生产环境应根据实际网络环境选择可信、稳定的镜像服务。
生产环境应当使用实际可用、可信赖、安全的镜像服务。
另外需要注意:
registry-mirrors 用于配置 Docker Hub Registry 的镜像加速地址。
它并不是:
“配置以后所有 Registry 都自动加速”。
如果企业内部已经部署 Harbor、私有 Registry 或其他镜像仓库,通常应该根据实际仓库架构单独配置。
哪些配置应该谨慎修改?
storage-driver
Docker 会根据实际环境选择合适的存储驱动。
如果确实需要修改 storage-driver,必须先确认:
- Docker Engine 版本;
- Linux 内核;
- 底层文件系统;
- 现有 Docker 数据;
- 业务运行情况。
已经运行生产业务的服务器尤其不要随意修改。
userland-proxy
网上经常能看到:
{ "userland-proxy": false}然后告诉你:
关闭
userland-proxy可以提高 Docker 网络性能。
这种说法过于简单。
它会改变 Docker 的端口发布行为,是否适合关闭取决于实际网络环境。
如果当前 Docker 网络没有问题,不要为了随意关闭。
iptables
更不要因为不理解 Docker 网络规则就配置:
{ "iptables": false}Docker 默认会通过 iptables 管理容器网络相关规则。
关闭以后可能导致:
- 容器网络访问异常;
- 端口发布异常;
- Docker 自动管理的网络规则失效等问题。
除非你明确知道自己在构建一套自定义网络方案,否则生产环境不要随便关闭。
dns
可以通过:
{ "dns": ["8.8.8.8", "1.1.1.1"]}为容器指定 DNS。
但这同样不是生产环境必配。
如果公司内部存在:
- 内部 DNS;
- Service Discovery;
- VPN DNS;
- 域名解析策略。
直接强制使用公共 DNS 反而可能导致内部域名无法解析。
因此 DNS 应该根据实际网络环境配置。
insecure-registries
这个配置允许 Docker 使用 HTTP Registry,或者访问使用不受信任 TLS 证书的 Registry。
例如:
{ "insecure-registries": ["registry.example.com:5000"]}生产环境应该尽量使用正常的 HTTPS Registry 和可信证书。
不要为了绕过证书问题就把 Registry 加入 insecure-registries。
debug
debug 可以开启 Docker daemon 调试日志:
{ "debug": true}排查 Docker 本身问题时可能有帮助。
但是生产环境长期打开 debug 通常没有必要。
一份够用的生产环境 daemon.json
{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "live-restore": true}如果实际存在 Docker Hub 拉取慢的问题,再根据网络环境增加
registry-mirrors。
常见问题
daemon.json 可以写注释吗?
不可以。daemon.json 必须是合法 JSON,不能使用 // 或 # 等方式添加注释。
为什么修改 daemon.json 后 Docker 启动失败?
首先执行:
dockerd --validate --config-file=/etc/docker/daemon.json如果配置验证通过,再检查:
journalctl -u docker -n 100 --no-pager通常可以快速定位 JSON 格式错误、配置冲突或不支持的配置项。
daemon.json 不存在,需要自己创建吗?
需要时可以自己创建。
daemon.json 默认不存在并不代表 Docker 有问题。
Docker 没有该文件时,会使用默认配置运行。
修改 daemon.json 后需要执行 systemctl daemon-reload 吗?
只修改 /etc/docker/daemon.json,通常不需要执行 systemctl daemon-reload;直接重启 Docker daemon 即可。
如果同时修改了 Docker 的 systemd unit、override 配置等 systemd 配置,才需要根据实际情况执行。
修改日志配置后,原来的容器为什么没有变化?
因为 daemon.json 中的默认日志配置主要作用于新创建的容器。
已经存在的容器不会因为修改 daemon.json 就自动改变日志配置。
可以通过:
docker inspect -f '{{json .HostConfig.LogConfig}}' <container>检查实际配置。
重启 Docker 会不会导致所有容器都重启?
不应该简单理解为“所有容器都会重启”。
Docker daemon 重启和主机重启是两件不同的事情。
live-restore 可以降低 daemon 重启对运行中容器的影响。
但具体行为还取决于 Docker 版本、容器运行状态、运行时以及具体维护操作。
生产环境修改 Docker 配置前仍然应该按照维护操作进行评估。
data-root 可以直接修改吗?
如果是新服务器,还没有重要容器和镜像,可以直接配置。
如果已经运行生产业务,不建议直接修改。
因为 Docker 原来的镜像、容器和其他数据仍然位于旧目录。
应该先停止 Docker、迁移数据,再修改配置并验证。
registry-mirrors 越多越好吗?
不是。
镜像源越多不代表一定越快,反而可能增加排查问题的复杂度。
生产环境优先选择稳定、可信、实际可用的镜像服务。
Docker Hub 拉取很慢,一定要配置 registry-mirrors 吗?
不一定。
还可以考虑:
- 使用企业内部 Registry;
- 使用云厂商镜像服务;
- 在内网部署 Harbor;
- 提前拉取常用基础镜像。
如果生产环境经常部署相同镜像,企业内部 Registry 往往比依赖公网镜像加速更容易管理。
需要把所有 daemon 配置都写进 daemon.json 吗?
完全没必要。
生产环境配置应该遵循:有需求再配置。
daemon.json 修改错了,Docker 起不来了怎么办?
先查看 Docker 服务状态:
systemctl status docker --no-pager然后查看详细日志:
journalctl -u docker -n 100 --no-pager如果确定是刚刚修改的 daemon.json 导致的问题,可以恢复备份:
cp /etc/docker/daemon.json.bak /etc/docker/daemon.json然后:
systemctl restart docker因此生产环境修改配置前一定建议先备份。
总结
本文中的配置示例主要用于生产环境实践说明,具体参数仍应根据 Docker Engine 版本、Linux 系统、磁盘、网络环境以及业务负载进行调整。
生产环境配置的核心原则:
Docker 的 daemon.json 并不是一份“配置越多越专业”的文件。
真正值得关注的,通常只有几个问题:
- 日志不能无限增长;
- Docker 数据不能无规划地占满系统盘;
- Docker 网络不能和实际网络发生冲突;
- daemon 维护操作尽量不要影响运行中的容器;
- 镜像拉取确实存在问题时,再配置镜像加速。
剩下的配置:能不改就不改。
参考资料
- Docker 官方文档:Docker 官方文档,详细介绍 Docker Engine、镜像、容器、网络、存储以及 Docker daemon 等功能。
- Docker daemon 官方文档:介绍 Docker daemon 的配置方式、daemon.json 配置文件以及常用 daemon 配置项。
- dockerd 命令参考:介绍 dockerd 命令及其启动参数,可用于了解 Docker daemon 的启动配置和参数。
- Docker 日志驱动官方文档:介绍 Docker 容器日志驱动以及 json-file、local 等日志配置方式。
- Docker Live Restore 官方文档:介绍 live-restore 配置,以及 Docker daemon 重启过程中保持容器运行的相关机制。
- Docker daemon Prometheus 指标:介绍 Docker daemon 的 Prometheus 监控指标。
- Docker 网络官方文档:介绍 Docker 网络、Bridge 网络、容器网络以及网络地址规划等相关内容。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时





