事情本身不复杂,线索都在日志里。阿里云 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。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
