Docker 内置 DNS,通常指 Docker Engine 的 嵌入式 DNS(embedded DNS)。它是 Docker 为容器提供的服务发现能力:在用户自定义网络中,容器可以通过 容器名、网络别名、Compose 服务名、Swarm 服务名 等互相访问,而不必记 IP。
一句话概括:
Docker 内置 DNS 监听在容器内的 127.0.0.11:53,负责解析同一自定义网络内的容器名称/别名/服务名;解析不了的名字再转发给外部 DNS。默认 bridge 网络通常不启用它。
1. 容器里的 /etc/resolv.conf
用户自定义网络
当你把容器接入自定义网络,例如:
docker network create mynet
docker run --rm --network mynet alpine cat /etc/resolv.conf
通常会看到:
nameserver 127.0.0.11
options ndots:0
127.0.0.11 就是 Docker 内置 DNS。
它不是 127.0.0.1,这样设计是为了避免和容器内自己运行的 DNS 服务冲突。
默认 bridge 网络
默认 bridge 网络下,容器通常直接使用宿主机的 DNS 配置:
docker run --rm alpine cat /etc/resolv.conf
里面一般没有 127.0.0.11,而是宿主机 /etc/resolv.conf 里的 DNS。
所以默认 bridge 下,容器不能通过容器名互相解析,除非用旧的 --link 或 --add-host 写进 /etc/hosts。
2. 解析流程
Linux 容器解析域名一般走 NSS:
/etc/nsswitch.conf: hosts: files dns
也就是:
- 先查
/etc/hosts - 再查 DNS
Docker 内置 DNS 的工作流程大致是:
- 容器应用发起 DNS 查询。
- 查询发到
127.0.0.11:53。 - Docker 内置 DNS 先看这个名字是不是当前网络内的:
- 容器名
- 网络别名
- Compose 服务名
- Swarm 服务名
- 如果是,返回对应容器的 IP。
- 如果不是,转发给外部 DNS:
docker run --dns=...daemon.json里的dns- 或宿主机
/etc/resolv.conf中的 DNS
所以它不是完整的递归 DNS,而是 内部服务发现 + 外部 DNS 转发。
3. 能解析哪些名字?
在用户自定义网络中,Docker 内置 DNS 可以解析:
--name指定的容器名--network-alias指定的网络别名docker network connect --alias添加的别名- Docker Compose 中的服务名
- Docker Swarm 中的服务名
- Swarm 中的
tasks.<service>
例如:
docker network create appnet
docker run -d --name db --network appnet --network-alias mysql mysql:8
docker run --rm --network appnet alpine sh
在容器里:
getent hosts db
getent hosts mysql
都能解析到 db 容器的 IP。
多个容器可以共享同一个网络别名,这时 DNS 可能返回多个 IP。
4. 默认 bridge vs 自定义网络
| 网络类型 | 是否有内置 DNS | 容器名解析 |
|---|---|---|
| 默认 bridge | 通常没有 | 不支持,除非 --link / --add-host |
| 自定义 bridge | 有,127.0.0.11 |
支持 |
| overlay | 有 | 支持,Swarm 服务发现 |
| host | 不使用容器网络命名空间 | 直接用宿主机 DNS |
| none | 无网络 | 无 DNS |
因此,生产环境推荐使用 用户自定义网络,而不是默认 bridge。
docker network create mynet
docker run -d --name web --network mynet nginx
docker run --rm --network mynet alpine getent hosts web
5. 外部 DNS 配置
可以通过这些方式指定外部 DNS:
docker run --dns=1.1.1.1 --dns=8.8.8.8 nginx
也可以全局配置 /etc/docker/daemon.json:
{
"dns": ["1.1.1.1", "8.8.8.8"],
"dns-search": ["example.com"],
"dns-opts": ["ndots:2"]
}
然后重启 Docker。
注意:
- 在用户自定义网络中,容器
/etc/resolv.conf仍然是nameserver 127.0.0.11。 --dns是告诉 Docker 内置 DNS:外部查询转发给谁。- 在默认 bridge 中,
--dns可能直接写入容器/etc/resolv.conf。 - 不要设置
--dns=127.0.0.11,会造成循环。
6. Compose 和 Swarm
Docker Compose
Compose 默认会创建一个自定义网络,所以服务名可以直接作为 DNS 名。
例如:
services:
web:
image: nginx
db:
image: mysql
在 web 容器里可以直接:
getent hosts db
Docker Swarm
Swarm 模式下:
- 默认
endpoint-mode vip:服务名解析为 VIP,再由 IPVS 负载均衡到任务。 endpoint-mode dnsrr:服务名解析为多个任务 IP。tasks.<service>可以解析到具体任务 IP。
7. 调试与常见问题
查看容器 DNS:
docker exec -it <container> cat /etc/resolv.conf
测试解析:
docker exec -it <container> getent hosts other
docker exec -it <container> nslookup other
docker exec -it <container> dig other
查看网络内容:
docker network inspect mynet
常见问题:
- 容器名解析不了:大概率不在同一个自定义网络。
- 默认 bridge 下解析不了:默认 bridge 不提供自动 DNS 服务发现。
- 外部域名解析失败:宿主机 DNS 可能是
127.0.0.53,比如 systemd-resolved,需要配置--dns或daemon.json。 - 手动改
/etc/resolv.conf后失效:容器重启或重建后会被 Docker 覆盖,应该用--dns等参数。 --link已过时:它主要写/etc/hosts,不是现代 Docker DNS 服务发现,推荐用自定义网络。- 容器 IP 会变:用名称访问,不要写死 IP。
总结
Docker 内置 DNS 是 Docker Engine 提供的嵌入式 DNS:
- 监听容器内
127.0.0.11:53 - 主要用于用户自定义网络、overlay 网络
- 解析容器名、网络别名、Compose 服务名、Swarm 服务名
- 未命中的查询转发给外部 DNS
- 默认 bridge 通常不启用,所以不能通过容器名互访
- 推荐使用自定义网络实现容器间服务发现
简单记:
自定义网络 + 容器名/服务名 + 127.0.0.11 = Docker 内置 DNS 服务发现。
docker network connect 的核心作用是:把一个已经存在的容器,动态接入到另一个已存在的 Docker 网络中,让它在不重启的情况下获得该网络的网卡、IP、路由和 DNS 服务发现能力。
一句话:
它相当于给运行中的容器“插上”一张新网卡,并把它注册到目标网络的 Docker 内置 DNS 里。
运行中容器的联网与断网
1. 基本语法
docker network connect [OPTIONS] NETWORK CONTAINER
示例:
docker network connect mynet mycontainer
表示把容器 mycontainer 连接到网络 mynet。
也可以指定别名和 IP:
docker network connect --alias db --ip 172.20.0.100 mynet mycontainer
之后在 mynet 网络中的其他容器里,就可以通过 db 或 mycontainer 访问它。
2. 它底层做了什么?
当执行 docker network connect 时,Docker 大致会做这些事:
-
在目标网络中创建一个 endpoint
- 每个“容器接入某个网络”的端点,Docker 内部称为 endpoint。
-
在容器网络命名空间里创建新网卡
- 通常是
eth1、eth2之类。 - 通过 veth pair 连接到目标网络的 bridge 或 overlay 等设备。
- 通常是
-
分配 IP 地址
- 如果没指定
--ip/--ip6,就从目标网络的 IPAM 池里分配。 - 如果指定了,必须在该网络子网内且未被占用。
- 如果没指定
-
配置路由
- 添加该网络子网的路由,让容器能通过新网卡访问该网络内的其他容器。
- 默认路由通常不会随意改变,仍以原网络为主。
-
注册到 Docker 内置 DNS
- 如果目标网络是用户自定义网络,Docker 会把容器的名称、主机名、
--alias别名注册到该网络的嵌入式 DNS 中。 - 这样该网络内的其他容器就能通过名字访问它。
- 它自己也能解析该网络内其他容器的名字。
- 如果目标网络是用户自定义网络,Docker 会把容器的名称、主机名、
-
更新容器 DNS 配置
- 如果容器之前只连默认 bridge,没有内置 DNS,连接到自定义网络后,Docker 通常会把容器内的
/etc/resolv.conf更新为:nameserver 127.0.0.11 - 即启用 Docker 内置 DNS。
- 如果容器之前只连默认 bridge,没有内置 DNS,连接到自定义网络后,Docker 通常会把容器内的
-
可能更新
/etc/hosts- 普通名称解析主要走内置 DNS。
- 如果用了
--link,则会额外写入/etc/hosts和环境变量。
-
持久化连接关系
- 连接关系会写入容器配置。
- 容器重启后,通常仍会保留这个网络连接,直到你执行
docker network disconnect。
3. 对 DNS 的影响
结合 Docker 内置 DNS 来看:
- 连接到用户自定义网络后,容器会加入该网络的 DNS 服务发现。
- 该网络内的其他容器可以通过:
- 容器名
- 网络别名
--alias - Compose 服务名
- Swarm 服务名
来解析它。
- 它也能解析同一网络内的其他容器。
- 别名只在目标网络内有效,不是全局的。
- 如果连接的是默认 bridge,通常不会启用内置 DNS,容器名解析仍然不生效。
例如:
docker network create appnet
docker run -d --name web --network appnet nginx
docker run -d --name debug alpine sleep 1d
docker network connect appnet debug
进入 debug 后:
docker exec -it debug getent hosts web
就能解析到 web 的 IP。
4. 常用选项
| 选项 | 作用 |
|---|---|
--alias |
在该网络中给容器添加别名,可多次指定 |
--ip |
指定 IPv4 地址 |
--ip6 |
指定 IPv6 地址 |
--link |
链接到另一个容器,会写 /etc/hosts 和环境变量 |
--link-local-ip |
添加链路本地地址 |
--driver-opt |
传递网络驱动特定选项 |
现代 Docker 中,推荐用 --alias + 自定义网络的内置 DNS,而不是旧的 --link。
5. 典型使用场景
-
多网络容器
一个容器同时连接前端网络和后端网络,比如 Web 容器既要访问前端,又要访问数据库。 -
调试容器加入目标网络
临时把排查用的 Alpine 容器连到生产网络里,用名字访问其他服务。 -
不重启容器添加网络
容器已经跑起来了,但需要临时接入另一个网络。 -
服务隔离与互通
前端网络和后端网络隔离,只让特定容器同时接入两个网络。
6. 注意事项
docker network connect通常作用于运行中的容器;连接关系会保存,重启后一般仍生效。- 断开网络用:
docker network disconnect mynet mycontainer host网络模式的容器共享宿主机网络命名空间,通常不能再连接其他网络。none网络容器可以再连接其他网络。- 指定
--ip时,IP 必须在目标网络子网内,且不能冲突。 - 多网络容器会有多个 IP,默认路由可能仍指向原网络,访问不同网络时按路由选择网卡。
- 如果应用已经缓存了 DNS,连接新网络后可能需要重启应用才能生效。
7. 和 docker run --network 的区别
docker run --network mynet:容器启动时就接入网络。docker network connect mynet mycontainer:容器运行中动态接入网络。
效果类似,都是让容器成为目标网络的一员,获得该网络的 IP、路由和 DNS 服务发现能力。
总结
docker network connect 做的是:
给已存在的容器动态添加一个网络接口,分配该网络的 IP,配置路由,注册到该网络的 Docker 内置 DNS,使容器无需重启就能参与该网络的通信和服务发现。
简单记:
它 = 动态插网卡 + 分配 IP + 配路由 + 注册 DNS。
