docker容器dns解析失败的根本原因是网络模式差异导致/etc/resolv.conf生成逻辑不一致,且该文件启动时被覆盖;正确做法是优先通过宿主机层面控制dns注入:一、单个容器用--dns参数临时指定;二、全局修改/etc/docker/daemon.json配置dns字段;三、自定义网络下结合内嵌dns(127.0.0.11)与上游dns;四、docker-compose中显式声明dns和dns_search。

Docker容器在Linux中默认会继承宿主机的DNS配置,但实际运行时经常出现“能ping通IP、却无法解析域名”的问题。根本原因在于不同网络模式下DNS行为不一致,而直接修改容器内 /etc/resolv.conf 通常无效(启动时会被覆盖)。正确做法是从宿主机层面控制DNS注入逻辑,具体按使用场景选择以下方式:
一、单个容器临时指定DNS(最常用)
适用于调试、CI/CD或一次性运行场景,优先级最高,完全覆盖其他配置:启动时用 --dns 参数传入一个或多个DNS服务器地址,顺序写入容器的 /etc/resolv.conf:
docker run --dns 114.114.114.114 --dns 8.8.8.8 -it alpine nslookup baidu.com
- 支持IPv4和IPv6(如
--dns 2001:4860:4860::8888) - 多个
--dns按顺序成为nameserver行 - 该方式对
docker-compose启动的容器也有效,但需在 service 级声明
二、全局统一配置所有新容器(推荐用于内网环境)
适合公司内网、私有云等需要统一DNS策略的场景,修改守护进程配置:编辑 /etc/docker/daemon.json,添加 dns、dns-search 和 dns-opts 字段:
{
"dns": ["192.168.1.1", "114.114.114.114"],
"dns-search": ["corp.local"],
"dns-opts": ["timeout:2", "attempts:2"]
}
- 保存后执行
sudo systemctl daemon-reload && sudo systemctl restart docker - 此后新建容器自动继承该配置,但仍可被
--dns覆盖 -
dns-search可补全短域名(如访问web自动尝试web.corp.local)
三、自定义网络 + 内嵌DNS(服务发现首选)
当你用docker network create 或 docker-compose 启动服务时,默认启用Docker内置DNS(127.0.0.11),它负责解析同网络容器名:
该模式下,容器的 /etc/resolv.conf 固定为:
nameserver 127.0.0.11 search mynet
-
127.0.0.11是Docker内嵌DNS地址,仅处理本网络内容器名和别名(--network-alias) - 它本身不递归查询公网域名,如需解析
baidu.com,必须额外配置上游DNS - 方法一:在
daemon.json中设置"dns",内嵌DNS会自动将其作为上游 - 方法二:启动容器时加
--dns,例如docker run --dns 8.8.8.8 --network mynet ...
四、Docker Compose中显式声明DNS
当项目依赖特定DNS且不想改动全局配置时,在docker-compose.yml 中直接定义:
示例(兼容自定义网络与上游解析):
version: '3.8'
services:
app:
image: nginx
dns:
- 127.0.0.11 # 保留内嵌DNS(可选,通常自动注入)
- 114.114.114.114
- 8.8.8.8
dns_search:
- corp.local
-
dns列表按顺序写入/etc/resolv.conf,不自动去重 - 若使用自定义网络,
127.0.0.11通常由Docker自动加入,手动写上更明确 -
dns_search控制域名补全行为,空数组[]表示禁用搜索域
不复杂但容易忽略











