我计划将单机服务器拆分为许多小的docker容器,但还没有找到“容器间通信”的好解决方案。这是我的目标方案:
我知道如何将容器链接在一起,以及如何公开端口,但是这些解决方案都不令我满意。
有什么解决方案可以像传统服务器网络中那样通过主机名(容器名称)在容器之间进行通信?
我计划将单机服务器拆分为许多小的docker容器,但还没有找到“容器间通信”的好解决方案。这是我的目标方案:
我知道如何将容器链接在一起,以及如何公开端口,但是这些解决方案都不令我满意。
有什么解决方案可以像传统服务器网络中那样通过主机名(容器名称)在容器之间进行通信?
Answers:
编辑:在Docker 1.9之后,docker network
命令(请参见下面的 https://stackoverflow.com/a/35184695/977939)是实现此目的的推荐方法。
我的解决方案是在主机上设置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
确保您的dnsmasq服务在上可用docker0
。然后,启动您的容器--dns HOST_ADDRESS
以使用此小型dns服务。
借助新的联网功能,您可以按容器的名称连接到容器,因此,如果创建新网络,则连接到该网络的任何容器都可以通过其名称访问其他容器。例:
1)创建新网络
$ docker network create <network-name>
2)将容器连接到网络
$ docker run --net=<network-name> ...
要么
$ docker network connect <network-name> <container-name>
3)按名称平容器
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
,新网络将不会创建环境变量,也不会与其他容器共享环境变量。
此功能当前不支持别名
docker-compose down,up,restart
?
bridge
由于向后兼容,它在默认网络中被禁用,但是是的,我同意,默认情况下应该启用它!
这应该是什么--link
是对的,至少主机名部分。
使用docker 1.10和PR 19242,将是:
docker network create --net-alias=[]: Add network-scoped alias for the container
(请参阅下面的最后一节)
那就是更新/etc/hosts
文件详细信息
除了环境变量,Docker还为
/etc/hosts
文件添加了源容器的主机条目。
例如,启动LDAP服务器:
docker run -t --name openldap -d -p 389:389 larrycai/openldap
并定义一个图像以测试该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
您可以使用--link在测试映像中将' openldap
'容器显示为' internalopenldap
':
docker run -it --rm --name ldp --link openldap:internalopenldap ldaptest
然后,如果键入“ lds”,则该别名将起作用:
ldapsearch -H ldap://internalopenldap ...
那将使人们返回。internalopenldap
从ldaptest
图像正确达到了含义。
当然,docker 1.7将添加libnetwork
,它提供了用于连接容器的本地Go实现。请参阅博客文章。
它通过容器网络模型(CNM)引入了更完整的体系结构
这将使用新的“ network”命令更新Docker CLI,并记录如何使用“ -net
”标志将容器分配给网络。
码头工人1.10有一个新的部分网络范围的别名,现在正式记录在network connect
:
链接提供了位于容器内的私有名称解析,而网络范围的别名为特定网络范围内的任何其他容器提供了一种由备用名称发现容器的方式。
与服务的使用者定义的链接别名不同,网络范围的别名是由向网络提供服务的容器定义的。继续上面的示例,
isolated_nw
使用网络别名在其中创建另一个容器。
$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17
--alias=[]
为容器添加网络范围的别名
您可以使用
--link
option链接另一个具有首选别名的容器您可以暂停,重新启动和停止连接到网络的容器。暂停的容器保持连接状态,可以通过网络检查来发现。停止容器后,直到重新启动它,它才会出现在网络上。
如果指定,重新启动已停止的容器时,将重新应用该容器的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
编辑:不再是前沿:http://blog.docker.com/2016/02/docker-1-10/
原始答案
我整夜都在与之抗争。如果您不担心前沿技术,则最新版本的Docker引擎和Docker都将实现libnetwork。
使用正确的配置文件(需要在版本2中放置),您将创建可以全部看到的服务。而且,好处是,您也可以使用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映射到主机名。
如果您想开箱即用的解决方案。一种解决方案是使用例如Kontena。它附带了Weave的网络覆盖技术,该技术用于为每个服务创建虚拟专用局域网,并且每个服务都可以通过service_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