Networking 如何通过“Docker”在Docker容器之间进行通信;主机名;

Networking 如何通过“Docker”在Docker容器之间进行通信;主机名;,networking,docker,Networking,Docker,我计划将我的Monothic服务器拆分为许多小型docker容器,但还没有找到一个很好的“容器间通信”解决方案。这是我的目标场景: 我知道如何将容器链接在一起以及如何公开端口,但这些解决方案都不能让我满意 是否有任何解决方案可以像在传统服务器网络中那样通过主机名(容器名)在容器之间进行通信?至少对于主机名部分来说应该是这样。 如果有,那将是: docker network create --net-alias=[]: Add network-scoped alias for the conta

我计划将我的Monothic服务器拆分为许多小型docker容器,但还没有找到一个很好的“容器间通信”解决方案。这是我的目标场景:

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

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

至少对于主机名部分来说应该是这样。
如果有,那将是:

docker network create --net-alias=[]: Add network-scoped alias for the container
(见下文最后一节)

这是什么细节

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

例如,启动LDAP服务器:

docker run -t  --name openldap -d -p 389:389 larrycai/openldap
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
并定义一个映像以测试该LDAP服务器:

docker run -t  --name openldap -d -p 389:389 larrycai/openldap
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
您可以使用--link在测试映像中将“
openldap
”容器公开为“
internalopenldap
”:

然后,如果键入“lds”,则该别名将起作用:

ldapsearch -H ldap://internalopenldap ...
这将使人们得到回报。意思是从
ldaptest
图像中正确访问
internalopenldap


当然,docker 1.7将添加一个用于连接容器的本机Go实现。请参阅。
它引入了一个更完整的体系结构,即容器网络模型(CNM)

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


docker 1.10有一个新的部分,现在:

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

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

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

您可以使用
--link
选项链接另一个具有首选别名的容器

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

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

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


据我所知,仅使用Docker是不可能的。您需要一些DNS来将容器ip:s映射到主机名

如果您想要现成的解决方案。一个解决方案是使用例如。它带有Weave的网络覆盖技术,该技术用于为每个服务创建虚拟专用LAN网络,每个服务都可以通过
服务\u name.kontena.local address
访问

下面是Wordpress应用程序的YAML文件的简单示例,其中Wordpress服务使用Wordpress-MySQL.kontena.local地址连接到MySQL服务器:

wordpress:                                                                         
  image: wordpress:4.1                                                             
  stateful: true                                                                   
  ports:                                                                           
    - 80:80                                                                      
  links:                                                                           
    - mysql:wordpress-mysql                                                        
  environment:                                                                     
    - WORDPRESS_DB_HOST=wordpress-mysql.kontena.local                              
    - WORDPRESS_DB_PASSWORD=secret                                                 
mysql:                                                                             
  image: mariadb:5.5                                                               
  stateful: true                                                                   
  environment:                                                                     
    - MYSQL_ROOT_PASSWORD=secret

编辑:在Docker 1.9之后,建议使用
Docker network
命令(见下文)来实现这一点


我的解决方案是在主机上设置一个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
#/bin/bash
#默认情况下,间隔时间为10秒
间隔=${INTERVAL:-10}
#dnsmasq配置目录
DNSMASQ_配置=${DNSMASQ_配置:-.}
#此脚本中使用的命令
DOCKER=${DOCKER:-DOCKER}
SLEEP=${SLEEP:-SLEEP}
TAIL=${TAIL:-TAIL}
声明-服务映射
虽然是真的
做
更改=错误
读行时
做
名称=${line##*}
ip=$(${DOCKER}inspect--format'{{{.NetworkSettings.IPAddress}}'$name)
如果[-z${service_map[$name]}]|【${service_map[$name]}!=$ip]#ip地址已更改
然后
服务映射[$name]=$ip
#写入文件
echo$name有一个新的IP地址$IP>&2
echo“主机记录=$name,$ip”>“${DNSMASQ_CONFIG}/docker-$name”
更改=真
fi

完成编辑:它不再是前沿:

原始答案
我和它斗争了一整夜。 如果您不怕前沿,最新版本的和都将实现libnetwork

有了正确的配置文件(需要放在版本2中),您将创建能够彼此看到的服务。另外,您还可以使用docker compose扩展它们(您可以扩展不绑定主机端口的任何服务)

这里有一个例子

以及此新版本的撰写文件的参考:

新的网络功能允许您通过以下方式连接到容器: 它们的名称,因此如果创建新网络,任何连接到 该网络可以通过名称到达其他容器。例如:

1)创建新网络

$ docker network create <network-name>       
$ docker run --net=<network-name> ...
$docker网络创建
2)将容器连接到网络

$ docker network create <network-name>       
$ docker run --net=<network-name> ...
$docker运行--net=。。。

$docker网络连接
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
docker exec-ti ping
来自c1的64字节(172.18.0.4):icmp_seq=1 ttl=64时间=0.137毫秒
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