容器DNS解析失败核心是/etc/resolv.conf未指向可用DNS或解析链路被拦截,需按宿主机、Docker守护进程、容器运行时三级优先级排查:先用cat /etc/resolv.conf和docker inspect确认配置来源,再依场景选--dns、daemon.json、bind挂载或compose配置修复。
容器内部无法解析外网域名,核心是 /etc/resolv.conf 没指向可用 dns 服务器,或解析链路被拦截。关键不在“换工具”,而在理清配置来源层级——宿主机、docker 守护进程、容器运行时三者存在明确覆盖关系,改错地方等于白忙。
先确认 DNS 配置从哪来
不查清楚就改,大概率无效:
- 进容器执行
cat /etc/resolv.conf:看到nameserver 127.0.0.11,说明走 Docker 内置转发器(可能慢/不可靠);看到127.0.0.53或::1,大概率是 systemd-resolved 干扰,Docker 默认会过滤这类地址 - 运行
docker inspect 容器名 | grep -A 5 "Dns\|NetworkMode",看实际生效的 DNS 设置和网络模式(比如是否用了自定义网络) - 检查宿主机
/etc/resolv.conf是否本身含无效 DNS(如仅内网 DNS、已下线的地址),Docker 默认会继承它
按场景选对修复方式
不同部署阶段,生效位置不同,硬套一种方法容易失败:
-
单次调试或快速验证:启动容器时加
--dns 8.8.8.8 --dns 1.1.1.1,跳过内置转发器,直连公共 DNS -
多容器统一管理(推荐长期用):修改
/etc/docker/daemon.json,加入{"dns": ["8.8.8.8", "1.1.1.1"]},再执行sudo systemctl restart docker -
必须复用宿主机 DNS(如内网环境):用
--mount type=bind,source=/etc/resolv.conf,target=/etc/resolv.conf,readonly挂载,但要确保宿主机配置本身有效 -
Docker Compose 环境:在
docker-compose.yml对应服务下直接写dns和dns_search字段,比改 daemon.json 更灵活、更易维护
验证是否真解决
改完别急着跑业务,先做最小化验证:
- 容器内执行
nslookup google.com和nslookup @8.8.8.8 google.com对比:前者失败后者成功,说明是转发链路问题;两者都失败,说明 DNS 服务器本身不可达 - 装诊断工具:
apk add bind-tools(Alpine)或apt-get install dnsutils(Ubuntu),再用dig +trace google.com看解析每一步卡在哪 - 若仍不通,检查是否被安全机制拦截:
ausearch -m avc -ts today | grep dns(SELinux)、iptables -L -n -t nat | grep :53(iptables 规则)
避开几个高频坑
很多“修了没用”其实是踩中了默认行为:
- 在自定义网络(
docker network create)里用--dns启动容器,该参数会被忽略,必须通过daemon.json或 Compose 的dns字段设置 -
Dockerfile中RUN echo 'nameserver 8.8.8.8' > /etc/resolv.conf在容器运行时会被 Docker 自动重写,不持久 - 用
--network=host时,/etc/resolv.conf是挂载的,但 DNS 查询走的是宿主机策略,得同步检查宿主机防火墙、代理或systemd-resolved状态


















