基于本文回答
0
评论

容器之间是如何通过容器名称或服务名称进行域名解析(DNS)的?

在 Docker 中,容器之间能够通过容器名称(Container Name)服务名称(Service Name)进行域名解析,核心依赖于 Docker 内部实现的 嵌入式 DNS 服务器(Embedded DNS Server)

下面为您详细拆解其工作原理、实现机制以及不同场景下的应用。


1. 核心前提:用户自定义网络(User-Defined Bridge)

这是最关键的一点:只有在使用“用户自定义网络”(如自己创建的 bridge 网络)时,Docker 的 DNS 解析才会生效。

  • 默认的 bridge 网络(不推荐): 如果你直接运行 docker run 而不指定网络,容器会被加入到默认的 bridge 网络中。在这个网络里,Docker 不提供容器名 DNS 解析,容器间只能通过 IP 地址通信。
  • 自定义网络(推荐): 当你创建并使用自定义网络时,Docker 会为该网络启动一个内置的 DNS 服务器(IP 通常为 127.0.0.11)。

快速验证:

bash
# 1. 创建一个自定义网络
docker network create my-net

# 2. 运行容器 A 并加入网络
docker run -d --name web-server --network my-net nginx

# 3. 运行容器 B 并通过容器名 ping 容器 A
docker run --rm --network my-net alpine ping -c 2 web-server

输出中会显示 web-server 被成功解析成了对应的容器 IP。


2. 内部工作原理(DNS 解析流程)

当容器 B 尝试连接 http://web-server 时,幕后发生了以下步骤:

  1. 修改 /etc/resolv.conf
    当容器启动并加入自定义网络时,Docker 会自动修改容器内的 /etc/resolv.conf 文件,将其中的 nameserver 指向 127.0.0.11(这是 Docker 嵌入式 DNS 服务的监听地址)。

  2. 发起 DNS 查询:
    容器 B 的应用程序发起对 web-server 的域名解析请求,请求被发送到 127.0.0.11:53

  3. Docker 内部 DNS 拦截并解析:
    Docker 守护进程(Docker Daemon)维护着一个动态的“容器名-IP”映射表。每当有新容器启动、停止或加入网络时,这个表就会实时更新。

    • Docker DNS 发现查询的是 web-server,并在映射表中找到了它在 my-net 网络中的 IP(例如 172.18.0.2),然后将该 IP 返回给容器 B。
  4. 外部域名转发(备用):
    如果容器查询的是一个外部域名(如 baidu.com),Docker 内部 DNS 无法解析,它会将请求转发给宿主机配置的 DNS 服务器(如 8.8.8.8 或本地 DNS)。


3. 不同场景下的解析方式

场景 A:Docker Compose(最常见)

在 Docker Compose 中,解析更加简单和直观。

  • 服务名(Service Name)即域名:
    yaml
    version: '3'
    services:
      web:
        image: nginx
      db:
        image: postgres
    在同一个 docker-compose.yml 中,Docker 会自动创建一个默认网络。web 容器可以直接通过 db 这个域名连接到数据库容器。

场景 B:网络别名(Network Aliases)

有时你希望一个容器有多个名字,或者用一个别名来代表它。

bash
docker run -d --name my-mysql --network my-net --network-alias database mysql

此时,其他容器既可以通过 my-mysql(容器名)解析,也可以通过 database(别名)解析。

场景 C:Docker Swarm 模式(服务发现与负载均衡)

在 Docker Swarm 集群中,解析机制升级为 VIP(Virtual IP) 机制:

  1. 你创建了一个名为 search-api 的服务,副本数(replicas)为 3。
  2. 其他容器解析 search-api 时,Docker DNS 不会直接返回那 3 个容器的实际 IP,而是返回一个 虚拟 IP (VIP)
  3. 当流量到达 VIP 时,Docker 内核的 IPVS(IP Virtual Server)会自动将请求负载均衡到后端那 3 个实际的容器中。

4. 总结

机制 默认 bridge 网络 用户自定义 bridge 网络 Docker Compose Docker Swarm
DNS 解析 ❌ 不支持 支持 支持 支持
解析对象 容器名、容器ID、别名 服务名 (Service Name) 服务名 (Service Name)
负载均衡 支持 (通过 VIP/DNS RR)
右滑查看面试常问