【问题标题】:How to create a bidirectional link between containers?如何在容器之间创建双向链接?
【发布时间】:2014-08-15 10:24:07
【问题描述】:

我必须链接两个容器,这样它们才能看到彼此。当然是以下...

docker run -i -t --name container1 --link container2:container2 ubuntu:trusty /bin/bash
docker run -i -t --name container2 --link container1:container1 ubuntu:trusty /bin/bash

...在第 1 行失败,因为容器需要启动并运行才能成为链接目标:

2014/08/15 03:20:27 Error response from daemon: Could not find entity for container2

创建双向链接的最简单方法是什么?

【问题讨论】:

  • 我最近的answer你可能会感兴趣。
  • 谢谢,这实际上也是我所做的(请参阅下面我自己的答案),并且它的工作非常可靠

标签: docker


【解决方案1】:

Docker 1.10 通过引入高级容器网络很好地解决了这个问题。 (详情:https://docs.docker.com/engine/userguide/networking/dockernetworks/

首先,创建一个网络。下面的示例创建了一个基本的“桥接”网络,该网络仅适用于一台主机。您可以查看 docker 更完整的文档,以使用覆盖网络跨主机执行此操作。

docker network create my-fancy-network

1.10 中的 Docker 网络现在在容器内创建一个特殊的 DNS 解析,可以以特殊方式解析名称。首先,您可以继续使用 --link,但正如您所指出的那样,您的示例不起作用。我建议在 docker run 命令中使用 --net-alias=:

docker run -i -t --name container1 --net=my-fancy-network --net-alias=container1 ubuntu:trusty /bin/bash
docker run -i -t --name container2 --net=my-fancy-network --net-alias=container2 ubuntu:trusty /bin/bash

请注意,使用 --name container2 设置容器名称,这也会创建一个 DNS 条目,而 --net-alias=container2 只是在网络上创建一个 DNS 条目,因此在这个特定示例中,您可以省略 --net -alias 但我把它留在那里以防你想重命名你的容器并且仍然有一个与你的容器名称不匹配的 DNS 别名。

(详情请看:https://docs.docker.com/engine/userguide/networking/configure-dns/

你来了:

root@4dff6c762785:/# ping container1
PING container1 (172.19.0.2) 56(84) bytes of data.
64 bytes from container1.my-fancy-network (172.19.0.2): icmp_seq=1 ttl=64 time=0.101 ms
64 bytes from container1.my-fancy-network (172.19.0.2): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from container1.my-fancy-network (172.19.0.2): icmp_seq=3 ttl=64 time=0.072 ms

从容器1

root@4f16381fca06:/# ping container2
PING container2 (172.19.0.3) 56(84) bytes of data.
64 bytes from container2.my-fancy-network (172.19.0.3): icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from container2.my-fancy-network (172.19.0.3): icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from container2.my-fancy-network (172.19.0.3): icmp_seq=3 ttl=64 time=0.062 ms

【讨论】:

  • 有没有办法在docker compose中设置?
  • 优秀的解决方案
【解决方案2】:

没有双向链接,因为您无法链接到非运行容器。

除非您是disabling inter-container communication,否则同一主机上的所有容器都可以看到网络上的任何其他容器。您只需向他们提供您要联系的容器的 IP 地址。

知道容器ip地址的最简单方法是运行:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' container1

你可以在启动两个容器后查看它(只是不要使用--link)。

如果您需要从container1内部自动知道container2的IP,有几个选项:

  1. 将 docker 套接字挂载为卷并使用远程 API

    docker run -i -t --name container1 -v /var/run/docker.sock:docker.sock ubuntu:trusty /bin/bash echo -e "GET /containers/container2/json HTTP/1.0\r\n" | nc -U /docker.sock | sed 's/.IPAddress":"([0-9.]).*/\1/'

  2. 使用编排服务……有很多选择,但我个人喜欢基于 DNS 的服务,例如 Skydockregistrator,并通过 dns 名称访问容器。

  3. 使用 docker 管理服务(例如 dockerize.it —免责声明:我正在研究它 —)将为您设置 DNS 服务。

【讨论】:

  • 非常感谢您的回答!我会暂时搁置这个问题,看看是否还有其他建议。
  • 关于建议“1”——你为什么只运行一个Docker容器到echo -e "GET...\r\n"
  • 该示例涵盖了“您需要从 container1 内部知道 container2 的 IP”的情况。这意味着您已经出于其他原因启动了容器。
【解决方案3】:

由于没有双向链接,我使用--net 参数解决了这个问题。这样他们就使用相同的网络堆栈,因此可以通过环回设备(localhost)相互访问。

docker run -d --name web me/myserver
docker run -d --name selenium --net container:web me/myotherserver

所以我可以从 web 访问 selenium 服务器(端口 4444),我的 selenium 服务器可以访问我的 web 服务器(端口 80)。

【讨论】:

  • 你是怎么知道4444和80的值的?
  • @Richard 端口只是因为我在容器中运行了一个 web 服务器和一个 selenium 服务器。此解决方案无需指定端口。一个容器中打开的任何端口都可以在另一个容器中使用。
  • 天才!我花了几个小时寻找这个!
  • 如何获取其他服务器的IP?
【解决方案4】:

这是我自己解决这个问题的方法:

首先,我检查所有容器(需要相互了解)并创建 dnsmasq 条目,如下所示:

for f in container1 container2 container3; do
  IP=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $f 2>/dev/null`
  if [ -n "$IP" ]; then
    echo $f "$IP"
    echo "host-record=$f,$IP" > /etc/dnsmasq.d/0host_$f
  else
    rm -f /etc/dnsmasq.d/0host_$f
  fi
done

然后我启动一个安装了 dnsmasq-base 的 dns 容器并启动 dnsmasq 服务:

docker run -d -P -h dns --name dns -v /etc/dnsmasq.d:/etc/dnsmasq.d:ro dns

然后我得到这个容器的 IP 地址:

DNS_IP=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' dns`

然后像这样启动容器:

docker run -d -P -h container1 --name container1 --dns $DNS_IP container1
docker run -d -P -h container2 --name container2 --dns $DNS_IP container2
docker run -d -P -h container3 --name container3 --dns $DNS_IP container3

这是我的设置的简化版本,但它显示了要点。我还添加了一种机制,当 /etc/dnsmasq.d 中的文件通过 inotify-tools 发生更改时,它会强制 dnsmasq 重新扫描。这样,每当一个容器重新启动时,所有容器都会获得新的 IP 地址。

【讨论】:

    【解决方案5】:

    我通过在每个容器的 /etc/hosts 中附加一个 ip-table 来解决这个问题,因为 example

    【讨论】:

    • 哦,我刚刚发现Docker 1.8.1版本会在彼此的/etc/hosts文件中自动注册和桥接每个正在运行的容器,所以不需要进一步配置。
    • 它有效!这太棒了!你能改写你的答案吗?我会接受它作为新的正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多