使用Docker内置DNS —— Docker Network

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

也就是:

  1. 先查 /etc/hosts
  2. 再查 DNS

Docker 内置 DNS 的工作流程大致是:

  1. 容器应用发起 DNS 查询。
  2. 查询发到 127.0.0.11:53。
  3. Docker 内置 DNS 先看这个名字是不是当前网络内的:
    • 容器名
    • 网络别名
    • Compose 服务名
    • Swarm 服务名
  4. 如果是,返回对应容器的 IP。
  5. 如果不是,转发给外部 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 大致会做这些事:

  1. 在目标网络中创建一个 endpoint

    • 每个“容器接入某个网络”的端点,Docker 内部称为 endpoint。
  2. 在容器网络命名空间里创建新网卡

    • 通常是 eth1、eth2 之类。
    • 通过 veth pair 连接到目标网络的 bridge 或 overlay 等设备。
  3. 分配 IP 地址

    • 如果没指定 --ip / --ip6,就从目标网络的 IPAM 池里分配。
    • 如果指定了,必须在该网络子网内且未被占用。
  4. 配置路由

    • 添加该网络子网的路由,让容器能通过新网卡访问该网络内的其他容器。
    • 默认路由通常不会随意改变,仍以原网络为主。
  5. 注册到 Docker 内置 DNS

    • 如果目标网络是用户自定义网络,Docker 会把容器的名称、主机名、--alias 别名注册到该网络的嵌入式 DNS 中。
    • 这样该网络内的其他容器就能通过名字访问它。
    • 它自己也能解析该网络内其他容器的名字。
  6. 更新容器 DNS 配置

    • 如果容器之前只连默认 bridge,没有内置 DNS,连接到自定义网络后,Docker 通常会把容器内的 /etc/resolv.conf 更新为:
      nameserver 127.0.0.11
    • 即启用 Docker 内置 DNS。
  7. 可能更新 /etc/hosts

    • 普通名称解析主要走内置 DNS。
    • 如果用了 --link,则会额外写入 /etc/hosts 和环境变量。
  8. 持久化连接关系

    • 连接关系会写入容器配置。
    • 容器重启后,通常仍会保留这个网络连接,直到你执行 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。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2026 Howell版权所有 备案号:冀ICP备19000576号