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

我打算把我的monolthic服务器分成许多小的docker集装箱,但还没有find一个好的“集装箱间通信”的解决scheme。 这是我的目标情景:

目标场景

我知道如何将容器连接在一起以及如何公开端口,但这些解决scheme都不令我满意。

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

编辑:在Docker 1.9之后, docker network命令(请参阅下面的https://stackoverflow.com/a/35184695/977939 )是实现此目的的推荐方法。


我的解决方法是在主机上设置一个dnsmasq来自动更新DNSlogging:“A”logging具有容器名称,并自动指向容器的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 

确保您的dnsmasq服务在docker0docker0 。 然后,用--dns HOST_ADDRESS启动你的容器来使用这个迷你dns服务。

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

新的networkingfunction允许您通过名称连接到容器,因此如果您创build新的networking,则连接到该networking的任何容器都可以通过名称到达其他容器。 例:

1)创build新的networking

 $ docker network create <network-name> 

2)将容器连接到networking

 $ docker run --net=<network-name> ... 

要么

 $ docker network connect <network-name> <container-name> 

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 

请参阅文档的这一部分;

注意:与传统links不同,新的networking不会创build环境variables,也不会与其他容器共享环境variables。

此function目前不支持别名

这应该是什么 – --link ,至less对于主机名部分。
docker1.10和公元19242 ,这将是:

 docker network create --net-alias=[]: Add network-scoped alias for the container 

(见下面的最后一节)

这就是更新/etc/hosts文件的细节

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

例如,启动一个LDAP服务器:

 docker run -t --name openldap -d -p 389:389 larrycai/openldap 

并定义一个图像来testingLDAP服务器:

 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 

您可以在testing映像中将“ openldap ”容器作为“ internalopenldap ”公开–link:

  docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest 

那么,如果你input'lds',那个别名就会起作用:

 ldapsearch -H ldap://internalopenldap ... 

这将返回人。 意思是从ldaptest映像正确地到达ldaptest


当然, libnetwork 1.7将添加libnetwork ,它提供了一个原生的Go实现来连接容器。 查看博客文章 。
它引入了更完整的体系结构,集装箱networking模型(CNM)

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

这将使用新的“networking”命令更新Docker CLI,并logging如何使用“ -net ”标志将容器分配给networking。


docker1.10有一个新的networking范围的别名 ,现在官方logging在network connect

尽pipe链接提供了在容器中本地化的专用名称parsing,但是networking范围的别名提供了一种容器在特定networking的范围内由其他容器的替代名称发现的方式。
与由服务使用者定义的链接别名不同,networking作用域别名是由向networking提供服务的容器定义的。

继续上面的例子,使用networking别名在isolated_nw创build另一个容器。

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

为容器添加networking范围的别名

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

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

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

确保IP地址可用的一种方法是在创buildnetworking时指定--ip-range ,并从该范围外select静态IP地址。 这可确保当此容器不在networking上时,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 

编辑 :它不再stream血了: http : //blog.docker.com/2016/02/docker-1-10/

原始答复
整整一个晚上我都和它斗争。 如果您不怕stream血,最新版本的Docker引擎和Docker组合都实现了libnetwork。

使用正确的configuration文件(需要在版本2中),您将创build将看到对方的服务。 而且,奖金,你也可以用docker-compose来扩展它们(你可以扩展任何你不想绑定端口的服务)

这是一个示例文件

 version: "2" services: router: build: services/router/ ports: - "8080:8080" auth: build: services/auth/ todo: build: services/todo/ data: build: services/data/ 

而这个新版本的撰写文件的参考: https : //github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md

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

如果你想开箱即用的解决scheme。 一个解决scheme是使用例如Kontena 。 它来自Weave的networking覆盖技术,该技术用于为每个服务创build虚拟专用LANnetworking,每个服务都可以通过service_name.kontena.local-address

这里是WordPress的应用程序的YAML文件的简单的例子,WordPress的服务连接到MySQL服务器与wordpress-mysql.kontena.local地址:

 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 

我刚刚find了Tumtum博客,并在官方的Docker文档中偶然发现了这一段 。 我不知道我是否一直错过这一段,或者是否是新添加的,但这应该是我需要的:)