事情本身不复杂,线索都在日志里。阿里云 4 核 8G 的 Ubuntu 22.04 跑 Docker 24.0.7,业务容器访问内部 API 报 could not resolve host,进容器 nslookup api.inner 返回 server can’t find,同一台宿主机上 dig 同样的域名秒回。

第一反应是「docker 的 userland-proxy 与自定义 bridge 冲突,UDP 53 的回包被丢弃」,验证下来不成立。

把日志和配置对完,能解释这个现象的基本就这几处。容器的 resolv.conf 里只有一个内网 DNS,请求出了网卡却被安全组挡在 53 端口。也可能是内网 DNS 只监听在 127.0.0.53,容器命名空间里没有这个地址,转发直接失败。

不容易想到的是,容器里装了 libc 的 stub resolver,ndots 设置让短域名先补全成 search 域再查。

上来先在容器里确认真正用的 DNS 地址

docker exec -it web cat /etc/resolv.conf

随后绕过容器,从宿主机直接验证 DNS 可用

dig @10.0.0.2 api.inner +short

指定 DNS 重建容器再试

docker run --rm --dns 10.0.0.2 busybox nslookup api.inner

自定义网络下固定 DNS 并核对解析

docker network create --driver bridge dnsnet && docker run --rm --network dnsnet --dns 10.0.0.2 busybox nslookup api.inner

改完先别撤,确认这几项。容器内 nslookup 与 getent hosts 都能返回内网地址,应用日志不再出现解析超时,重试计数器归零。

这里还有个坑。别在容器里直接改 resolv.conf,重启就丢;DNS 地址要写进 daemon.json 或者 compose 的 dns 字段,安全组记得放行出方向的 UDP 53。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189