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

dfty9e19  于 2023-11-17  发布在  Docker
关注(0)|答案(5)|浏览(154)

我计划将我的单体服务器拆分成许多小的Docker容器,但还没有找到一个很好的解决方案来实现“容器间通信”。这是我的目标场景:


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

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

f2uvfpb9

f2uvfpb91#

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

1)新建网络

$ docker network create <network-name>

字符串

2)容器接入网络

$ docker run --net=<network-name> --name=<container-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不同,新的网络不会创建环境变量,也不会与其他容器共享环境变量。

此功能目前不支持别名

kh212irz

kh212irz2#

编辑:在Docker 1.9之后,docker network命令(参见下面的https://stackoverflow.com/a/35184695/977939)是实现此功能的推荐方法。
我的解决方案是在主机上设置一个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://docs.blowb.org/setup-host/dnsmasq.html

uelo1irk

uelo1irk3#

应该是what --link is for,至少对于主机名部分是这样。
对于docker 1.10, and PR 19242,这将是:

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

字符串
(see(见下文最后一节)
更新/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实现来连接容器。参见blog post
它引入了一个更完整的架构,即容器网络模型(CNM)
x1c 0d1x的数据
这将使用新的“network”命令更新Docker CLI,并记录如何使用“-net“标志将容器分配给网络。
docker 1.10新增了一节Network-scoped alias,现在是officially documented in network connect
虽然链接提供了在容器内本地化的私有名称解析,但网络范围的别名提供了一种方法,使特定网络范围内的任何其他容器可以通过备用名称发现容器。
与由服务的消费者定义的链接别名不同,网络范围的别名由向网络提供服务的容器定义。
继续上面的示例,在isolated_nw中使用网络别名创建另一个容器。

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

--alias=[]


为容器添加网络范围的别名
您可以使用--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

b09cbbtk

b09cbbtk4#

编辑:不再是出血边缘:http://blog.docker.com/2016/02/docker-1-10/
原始答案

如果你不害怕前沿,最新版本的Docker engineDocker 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

ua4mk5z4

ua4mk5z45#

据我所知,只使用Docker是不可能的。你需要一些DNS来Map容器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

字符串

相关问题