在 Docker 的自定义网络(包括 Docker Compose 定义的网络)中,所有容器默认使用 内置的 DNS 服务器 127.0.0.11
来实现服务发现。该机制是 Docker 实现容器间通过服务名(Service Name)
直接通信的核心功能。
内置 DNS 服务器的作用
127.0.0.11
是 Docker 内置的 DNS 服务器地址,每个容器在启动时会自动配置该地址作为默认 DNS
- 它负责解析同一 Docker 网络内的服务名称(Service Name)到对应容器的 IP 地址
- 例如:如果容器
web
和 db
在同一个网络中,web
可以通过 db
这个主机名直接访问 db
容器
DNS 解析流程
当容器发起 DNS 查询时(如 ping db
或访问其他服务名),流程如下:
- 请求拦截:容器的 DNS 请求会被重定向到本地的
127.0.0.11
- 通过 Linux 的
iptables
或 nftables
规则实现
- 即使容器的
/etc/resolv.conf
中配置了外部 DNS,Docker 也会强制将 DNS 查询路由到内置 DNS
- 内置 DNS 解析:Docker 的内置 DNS 服务器会检查请求的域名是否属于当前网络中的服务名或别名
- 如果匹配,则返回对应容器的 IP 地址
- 如果不匹配(如外部域名
example.com
),则将请求转发给宿主机的 DNS 服务器
- 服务发现机制:Docker 维护了一个服务名称与容器 IP 的映射表:
- 每个服务名(如
db
)会被解析为该服务所有副本(容器)的 IP 地址(支持负载均衡)。
- 如果服务有多个实例(如使用
deploy.replicas
),内置 DNS 会以轮询(Round Robin)方式返回 IP。
服务名称与网络别名
- 在 Docker Compose 中,服务名称(
service_name
)会自动注册为 DNS 名称。
- 可以通过
networks
配置为服务添加自定义别名,例如:
services:
web:
networks:
app_net:
aliases:
- custom-web
此时其他容器可以通过 web
或 custom-web
访问该服务。
网络隔离与跨网络解析
- 同一网络内的容器:直接通过服务名解析
- 不同网络的容器:默认无法通过服务名解析,除非显式配置
networks
或使用 Docker 的 --link
(已废弃)
- 跨网络通信:需要将容器加入多个网络,或使用外部 DNS 配置
验证&示例
可以通过以下命令验证容器的 DNS 配置:
# 创建网络
docker network create dev
# 启动两个容器
docker run -it -d --rm --network dev --name web xiexianbin/ubuntu:24.04 bash
docker run -it -d --rm --network dev --name db xiexianbin/ubuntu:24.04 bash
# `web` 可以通过 `db` 这个主机名直接访问 `db` 容器
$ docker exec -it web bash
root@d241b54ab245:/# ping -c 1 db
PING db (172.18.0.3) 56(84) bytes of data.
64 bytes from db.dev (172.18.0.3): icmp_seq=1 ttl=64 time=0.113 ms
--- db ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.113/0.113/0.113/0.000 ms
# 测试 DNS 解析
root@d241b54ab245:/# nslookup db
Server: 127.0.0.11
Address: 127.0.0.11#53
Non-authoritative answer:
Name: db
Address: 172.18.0.3
关键特性
- 动态更新:当容器重启或缩放时,DNS 映射会自动更新
- 高性能:内置 DNS 避免了外部 DNS 查询延迟
- 安全性:仅解析 Docker 网络内的服务,防止 DNS 泄漏
扩展
- 非 Docker 网络流量:如果容器需要访问外部域名,内置 DNS 会将请求转发给宿主机的 DNS
- 自定义 DNS 配置:可以通过
dns
字段覆盖默认行为(例如指定上游 DNS):
services:
web:
dns:
- 8.8.8.8
- 8.8.4.4
- docker 容运行 nginx,如果需要
nginx upstream
中使用容器名,需要配置 resolver 127.0.0.11;
(参考)
总结
Docker 的内置 DNS 服务器 127.0.0.11
是容器间服务发现的核心组件,通过将服务名称动态解析为容器 IP,实现了简单高效的服务通信。这一机制无需额外配置即可支持微服务架构中的服务发现需求。