如何让所有Docker容器使用容器内运行的CoreDNS作为DNS服务器?
强制Docker容器默认使用自建CoreDNS作为DNS的可行方案
以下方案按易用性、稳定性排序,均不需要在每个docker-compose配置中单独写死动态变化的容器IP。
方案一:绑定CoreDNS到Docker网桥固定网关(最推荐)
Docker网桥的网关IP属于Docker网络层面的固定地址,完全不依赖CoreDNS容器的动态IP,重启容器、重建容器都不会影响配置有效性。
- 调整CoreDNS容器的启动参数,将53端口(TCP/UDP都需要覆盖)仅映射到Docker网桥的网关地址:默认bridge网桥的网关固定为
172.17.0.1,如果使用自定义bridge网桥,网关为创建网络时指定子网的第一个地址(比如自定义子网172.20.0.0/16对应网关为172.20.0.1)。
对应端口映射的启动参数如下:
该配置不会把CoreDNS暴露到公网,仅允许Docker内部网络的容器访问,安全性可控。-p 172.17.0.1:53:53/udp -p 172.17.0.1:53:53/tcp注意:该映射仅绑定Docker网桥IP,不会和宿主机本地监听127.0.0.1、公网IP的53端口服务冲突,不需要停用宿主机自带的systemd-resolved服务。
- 修改Docker全局配置文件
/etc/docker/daemon.json,添加全局DNS配置指向网桥网关IP:
如果文件中已有其他配置项,注意JSON格式规范,用逗号分隔不同配置项即可。{ "dns": ["172.17.0.1"] } - 重启Docker服务让全局配置生效:
后续所有新建容器都会默认把该网关地址作为DNS服务器,DNS请求会自动转发到监听在该地址的CoreDNS服务,完全不需要关心CoreDNS容器本身的IP变化。systemctl restart docker
提前检查CoreDNS的Corefile配置:不要配置ACL规则拦截Docker私有网段(172.16.0.0/12等)的查询请求,同时确认forward插件配置的上游DNS可用。
方案二:给CoreDNS分配固定容器IP(适合不想映射端口到宿主机的场景)
如果不希望CoreDNS端口映射到宿主机网桥,可以直接给CoreDNS分配固定不变的容器IP:
- 先创建一个自定义bridge网络(默认bridge网络不支持固定IP等高级配置),指定固定子网段:
docker network create --subnet=172.25.0.0/16 dns-net - 启动CoreDNS容器时,指定接入该网络并分配同子网的空闲固定IP:
只要不删除docker run --network dns-net --ip 172.25.0.53 -d <你的coredns镜像及其他启动参数>dns-net这个自定义网络,172.25.0.53这个IP就不会因为CoreDNS容器重启、重建发生变化。 - 同样修改
/etc/docker/daemon.json,把全局DNS设置为172.25.0.53,同时配置所有新建容器默认接入dns-net网络(可在daemon.json中通过default-address-pools配置默认网络,或在compose中统一引用该外部网络),重启Docker服务后配置即可生效。
配置验证
配置完成后可以启动一个临时测试容器,检查DNS配置是否生效:
docker run --rm alpine cat /etc/resolv.conf
输出中的nameserver为你配置的DNS地址后,再执行nslookup命令测试公网、内网域名解析是否正常即可。
内容的提问来源于stack exchange,提问作者Ian Gregson
相关产品推荐
相关产品推荐

