Ray 的记录站

日常开发实践记录

0%

Docker DNS 简介

本文介绍 Container 是如何发现各自存在的. 即:

  • 理解 Docker 内部虚拟网络中容器如何利用 DNS 简化相互通信
  • DNS 在自定义网络中如何工作
  • 使用 --link 在默认的 bridge 网络中启用 DNS

因为 Docker 中的容器和网络都是动态的, 所以不能依靠某个容器的 IP 地址来进行可靠通信, 必须有一种机制在即使容器 IP 发生变化后, 仍然能让通信可靠地进行下去.

Docker daemon 拥有一个内建的 DNS 服务器, 所有的容器默认都使用这个服务器. 默认情况下, Docker 使用容器名称作为容器的 hostname, 不过可以自定义 alias.

演示

新建两个容器, 分别名为 n1, n2, 容器连接到同一个网络 my_app_net, 确保两个容器都在运行.

运行如下命令:

1
docker container exec -it n1 ping n2

输出如下所示:

1
2
3
4
5
64 bytes from n2.my_app_net (172.18.0.3): icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from n2.my_app_net (172.18.0.3): icmp_seq=2 ttl=64 time=0.099 ms
64 bytes from n2.my_app_net (172.18.0.3): icmp_seq=3 ttl=64 time=0.100 ms
64 bytes from n2.my_app_net (172.18.0.3): icmp_seq=4 ttl=64 time=0.096 ms
64 bytes from n2.my_app_net (172.18.0.3): icmp_seq=5 ttl=64 time=0.105 ms

但默认的网络 bridge 中不能进行 ping 名字, 原因就是它没有使用默认的 DNS 服务器, 比如将 n1n2 连接到默认网络再 ping:

1
docker container exec -it n1 ping n2

则输出为:

1
ping: n2: Name or service not known

不过可以使用 --link 命令将其中的容器连接起来, 但最好的办法还是创建新的虚拟网络.

DNS Round Robin

这个概念就是同一个 DNS 记录的名字可以解析到多个 IP, 这样保证多个服务器可用.

在 Docker 中, 可以让位于某个虚拟网络下的多个容器都响应同一个名字.

方法就是使用 -network-alias, 这样就可以给容器一个额外的 DNS 名字, 让它响应某个名字.

这样可以让比如生产和测试环境 APP 响应同一个 DNS 名字. 另外就是多个服务容器部署在同一个虚拟网络下, 可以使用同一个 DNS 名字, 起类似负载均衡的效果, 但又不是真正的负载均衡, 因为服务的选择并不是根据负载决定的…

  1. 创建一个新的网络 dude:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ➜  ~ docker network create dude
    2d12f6430cd4e4a0c86ce8c4b5971c1f1d5e36a469783dc11024301f3b01455f
    ➜ ~ docker network ls
    NETWORK ID NAME DRIVER SCOPE
    6dd4c3f4dabd bridge bridge local
    2d12f6430cd4 dude bridge local
    9565b813a90a host host local
    d2a30bfc26bf my_app_net bridge local
    a1606d06a4af none null local
  2. 启动两个 elasticsearch:2 的容器, 名称让 Docker 随机分配, 重复两次执行如下命令生成两个容器:

    1
    docker container run -d --net dude --net-alias search elasticsearch:2

    上述命令将容器连接到 dude 网络中, 并指定它的网络别名为 search.

  3. 验证可以通过 search 这个 DNS 名字访问到这两个容器:

    1
    docker container run --rm --net dude alpine nslookup search

    输出如下所示:

    1
    2
    3
    4
    Name:   search
    Address: 172.19.0.2
    Name: search
    Address: 172.19.0.3
  4. 验证每次请求会分配到不同的容器:

    1
    docker container run --rm --net dude centos curl -s search:9200