如何通过 "hostname" 在 Docker 个容器之间通信
How to communicate between Docker containers via "hostname"
我计划将我的单体服务器拆分成许多小的 docker 容器,但还没有为 "inter-container communication" 找到好的解决方案。这是我的目标场景:
我知道如何 link 容器以及如何公开端口,但是 none 这些解决方案让我满意。
有没有像传统服务器网络中那样通过主机名(容器名称)在容器之间进行通信的解决方案?
至少主机名部分应该是 what --link
is for。
使用 docker 1.10, and PR 19242,即:
docker network create --net-alias=[]: Add network-scoped alias for the container
(见下文最后一节)
这就是Updating the /etc/hosts
file详情
In addition to the environment variables, Docker adds a host entry for the source container to the /etc/hosts
file.
例如,启动 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 ...
那 return 个人。意思是从 ldaptest
图像正确到达 internalopenldap
。
当然,docker1.7会加上libnetwork
, which provides a native Go implementation for connecting containers. See the blog post。
它引入了一个更完整的架构,容器网络模型(CNM)
这将使用新的“网络”命令更新 Docker CLI,并记录如何使用“-net
”标志将容器分配给网络。
docker 1.10 有一个新部分 Network-scoped alias, now officially documented in network connect
:
While links provide private name resolution that is localized within a container, the network-scoped alias provides a way for a container to be discovered by an alternate name by any other container within the scope of a particular network.
Unlike the link alias, which is defined by the consumer of a service, the network-scoped alias is defined by the container that is offering the service to the network.
Continuing with the above example, create another container in isolated_nw
with a network alias.
$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17
--alias=[]
Add network-scoped alias for the container
You can use --link
option to link another container with a preferred alias
You can pause, restart, and stop containers that are connected to a network. Paused containers remain connected and can be revealed by a network inspect. When the container is stopped, it does not appear on the network until you restart it.
If specified, the container's IP address(es) is reapplied when a stopped container is restarted. If the IP address is no longer available, the container fails to start.
One way to guarantee that the IP address is available is to specify an --ip-range
when creating the network, and choose the static IP address(es) from outside that range. This ensures that the IP address is not given to another container while this container is not on the network.
$ 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
据我所知,仅使用 Docker 这是不可能的。您需要一些 DNS 来将容器 ip:s 映射到主机名。
如果您想要开箱即用的解决方案。一种解决方案是使用例如 Kontena。它带有来自 Weave 的网络覆盖技术,该技术用于为每个服务创建虚拟专用 LAN 网络,每个服务都可以通过 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
编辑:在 Docker 1.9 之后,docker network
命令(见下文 )是实现此目的的推荐方法。
我的解决方案是在主机上设置一个 dnsmasq 以自动更新 DNS 记录:"A" 记录有容器的名称并自动指向容器的 IP 地址(每 10 秒)。 automatic updating script 粘贴在这里:
#!/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 服务。
编辑:它不再是最前沿的了:http://blog.docker.com/2016/02/docker-1-10/
原答案
我整晚都在和它战斗。
如果你不怕前沿,最新版本的 Docker engine and Docker compose 都实现了 libnetwork。
使用正确的配置文件(需要放在版本 2 中),您将创建相互可见的服务。而且,奖励,您也可以使用 docker-compose 扩展它们(您可以扩展任何您想要的不绑定主机端口的服务)
这是一个例子file
version: "2"
services:
router:
build: services/router/
ports:
- "8080:8080"
auth:
build: services/auth/
todo:
build: services/todo/
data:
build: services/data/
以及这个新版compose文件的参考资料:
https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md
新的网络功能允许您通过以下方式连接到容器
他们的名字,所以如果你创建一个新网络,任何连接到的容器
该网络可以通过名称访问其他容器。示例:
1) 创建新网络
$ docker network create <network-name>
2) 将容器连接到网络
$ 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
参见文档的 this 部分;
注意: 与传统 links
不同,新网络 不会 创建环境变量,也不会与其他容器共享环境变量.
此功能目前不支持别名
我计划将我的单体服务器拆分成许多小的 docker 容器,但还没有为 "inter-container communication" 找到好的解决方案。这是我的目标场景:
我知道如何 link 容器以及如何公开端口,但是 none 这些解决方案让我满意。
有没有像传统服务器网络中那样通过主机名(容器名称)在容器之间进行通信的解决方案?
至少主机名部分应该是 what --link
is for。
使用 docker 1.10, and PR 19242,即:
docker network create --net-alias=[]: Add network-scoped alias for the container
(见下文最后一节)
这就是Updating the /etc/hosts
file详情
In addition to the environment variables, Docker adds a host entry for the source container to the
/etc/hosts
file.
例如,启动 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 ...
那 return 个人。意思是从 ldaptest
图像正确到达 internalopenldap
。
当然,docker1.7会加上libnetwork
, which provides a native Go implementation for connecting containers. See the blog post。
它引入了一个更完整的架构,容器网络模型(CNM)
这将使用新的“网络”命令更新 Docker CLI,并记录如何使用“-net
”标志将容器分配给网络。
docker 1.10 有一个新部分 Network-scoped alias, now officially documented in network connect
:
While links provide private name resolution that is localized within a container, the network-scoped alias provides a way for a container to be discovered by an alternate name by any other container within the scope of a particular network.
Unlike the link alias, which is defined by the consumer of a service, the network-scoped alias is defined by the container that is offering the service to the network.Continuing with the above example, create another container in
isolated_nw
with a network alias.
$ docker run --net=isolated_nw -itd --name=container6 -alias app busybox
8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17
--alias=[]
Add network-scoped alias for the container
You can use
--link
option to link another container with a preferred aliasYou can pause, restart, and stop containers that are connected to a network. Paused containers remain connected and can be revealed by a network inspect. When the container is stopped, it does not appear on the network until you restart it.
If specified, the container's IP address(es) is reapplied when a stopped container is restarted. If the IP address is no longer available, the container fails to start.
One way to guarantee that the IP address is available is to specify an
--ip-range
when creating the network, and choose the static IP address(es) from outside that range. This ensures that the IP address is not given to another container while this container is not on the network.
$ 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
据我所知,仅使用 Docker 这是不可能的。您需要一些 DNS 来将容器 ip:s 映射到主机名。
如果您想要开箱即用的解决方案。一种解决方案是使用例如 Kontena。它带有来自 Weave 的网络覆盖技术,该技术用于为每个服务创建虚拟专用 LAN 网络,每个服务都可以通过 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
编辑:在 Docker 1.9 之后,docker network
命令(见下文
我的解决方案是在主机上设置一个 dnsmasq 以自动更新 DNS 记录:"A" 记录有容器的名称并自动指向容器的 IP 地址(每 10 秒)。 automatic updating script 粘贴在这里:
#!/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 服务。
编辑:它不再是最前沿的了:http://blog.docker.com/2016/02/docker-1-10/
原答案
我整晚都在和它战斗。
如果你不怕前沿,最新版本的 Docker engine and Docker compose 都实现了 libnetwork。
使用正确的配置文件(需要放在版本 2 中),您将创建相互可见的服务。而且,奖励,您也可以使用 docker-compose 扩展它们(您可以扩展任何您想要的不绑定主机端口的服务)
这是一个例子file
version: "2"
services:
router:
build: services/router/
ports:
- "8080:8080"
auth:
build: services/auth/
todo:
build: services/todo/
data:
build: services/data/
以及这个新版compose文件的参考资料: https://github.com/docker/compose/blob/1.6.0-rc1/docs/networking.md
新的网络功能允许您通过以下方式连接到容器 他们的名字,所以如果你创建一个新网络,任何连接到的容器 该网络可以通过名称访问其他容器。示例:
1) 创建新网络
$ docker network create <network-name>
2) 将容器连接到网络
$ 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
参见文档的 this 部分;
注意: 与传统 links
不同,新网络 不会 创建环境变量,也不会与其他容器共享环境变量.
此功能目前不支持别名