如何通过"hostname"在Docker容器之间进行通信

Pat*_*ard 78 networking docker

我计划将我的monolthic服务器拆分成许多小型docker容器,但尚未找到"容器间通信"的良好解决方案.这是我的目标场景:

目标方案

我知道如何将容器链接在一起以及如何公开端口,但这些解决方案都不能令我满意.

是否有任何解决方案可以通过容器之间的主机名(容器名称)进行通信,就像在传统的服务器网络中一样?

Hem*_*ela 180

新的网络功能允许您按名称连接到容器,因此,如果您创建新网络,则连接到该网络的任何容器都可以通过其名称访问其他容器.例:

1)创建新网络

$ docker network create <network-name>       
Run Code Online (Sandbox Code Playgroud)

2)将容器连接到网络

$ docker run --net=<network-name> ...
Run Code Online (Sandbox Code Playgroud)

要么

$ docker network connect <network-name> <container-name>
Run Code Online (Sandbox Code Playgroud)

3)按名称Ping容器

docker exec -ti <container-name-A> ping <container-name-B> 

64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms
Run Code Online (Sandbox Code Playgroud)

请参阅文档的部分;

注意:与旧版本不同links,新网络不会创建环境变量,也不会与其他容器共享环境变量.

此功能目前不支持别名

  • 效果很好.为什么默认网络默认不启用? (4认同)
  • @Stéphane 由于向后兼容性,它在默认的“bridge”网络中被禁用,但是是的,我同意,它_应该_肯定在默认情况下启用! (4认同)

xuh*_*dev 26

编辑:在Docker 1.9之后,docker network命令(见下面的 /sf/answers/2462928681/)是实现此目的的推荐方法.


我的解决方案是在主机上设置dnsmasq以自动更新DNS记录:"A"记录具有容器名称并自动指向容器的IP地址(每10秒).该自动更新脚本被粘贴在这里:

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done
Run Code Online (Sandbox Code Playgroud)

确保您的dnsmasq服务可用docker0.然后,启动您的容器--dns HOST_ADDRESS以使用此迷你DNS服务.

参考:http://docs.blowb.org/setup-host/dnsmasq.html


Von*_*onC 13

这应该是什么--link是对的,至少主机名部分.
使用docker 1.10和PR 19242,它将是:

docker network create --net-alias=[]: Add network-scoped alias for the container
Run Code Online (Sandbox Code Playgroud)

(见下文最后一节)

这就是更新/etc/hosts文件详细信息

除了环境变量之外,Docker还将源容器的主机条目添加到/etc/hosts文件中.

例如,启动LDAP服务器:

docker run -t  --name openldap -d -p 389:389 larrycai/openldap
Run Code Online (Sandbox Code Playgroud)

并定义一个映像来测试该LDAP服务器:

FROM ubuntu
RUN apt-get -y install ldap-utils
RUN touch /root/.bash_aliases
RUN echo "alias lds='ldapsearch -H ldap://internalopenldap -LL -b
ou=Users,dc=openstack,dc=org -D cn=admin,dc=openstack,dc=org -w
password'" > /root/.bash_aliases
ENTRYPOINT bash
Run Code Online (Sandbox Code Playgroud)

您可以使用--link在测试图像中公开' openldap'容器' internalopenldap':

 docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest
Run Code Online (Sandbox Code Playgroud)

然后,如果您输入'lds',该别名将起作用:

ldapsearch -H ldap://internalopenldap ...
Run Code Online (Sandbox Code Playgroud)

那会让人回归.internalopenldapldaptest图像中正确地达到了意义.


当然,docker 1.7将添加libnetwork,它提供了一个用于连接容器的本机Go实现.查看博客文章.
它引入了一个更完整的架构,包含集装箱网络模型(CNM)

https://blog.docker.com/media/2015/04/cnm-model.jpg

这将使用新的"网络"命令更新Docker CLI,并记录如何使用" -net"标志将容器分配给网络.


docker 1.10有一个新的网络范围别名,现在正式记录在network connect:

虽然链接提供了在容器中本地化的私有名称解析,但网络范围的别名提供了一种方法,可以通过特定网络范围内的任何其他容器以备用名称发现容器.
与由服务的使用者定义的链接别名不同,网络范围的别名由向网络提供服务的容器定义.

继续上面的示例,isolated_nw使用网络别名创建另一个容器.

$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17

--alias=[]         
Run Code Online (Sandbox Code Playgroud)

为容器添加网络范围的别名

您可以使用--link选项将另一个容器与首选别名链接

您可以暂停,重新启动和停止连接到网络的容器.暂停的容器保持连接状态,并可通过网络检查显示.当容器停止时,在重新启动容器之前,它不会出现在网络上.

如果指定,则在重新启动已停止的容器时重新应用容器的IP地址.如果IP地址不再可用,则容器无法启动.

保证IP地址可用的一种方法是指定--ip-range创建网络的时间,并从该范围外选择静态IP地址.这可确保在此容器不在网络上时,不会将IP地址提供给另一个容器.

$ docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network

$ docker network connect --ip 172.20.128.2 multi-host-network container2
$ docker network connect --link container1:c1 multi-host-network container2
Run Code Online (Sandbox Code Playgroud)

  • --link的问题是,如果不重新启动链接容器,则无法重新启动容器.当您查看我的图形时,重新启动MySQL容器将导致其他容器重启的级联. (3认同)