通过主机名发现Docker容器无效

时间:2019-11-26 16:27:00

标签: docker docker-swarm docker-networking docker-stack docker-network

我将位于/tmp/compose.yml的以下docker compose文件用于docker堆栈部署:

version: "3.6"

services:
  service-A:
    image: service-A
    networks:
      - net
    hostname: "service-A-{{.Task.Slot}}"
    deploy:
      replicas: 2

  service-B:
    image: service-B
    networks:
      - net
    hostname: "service-B-{{.Task.Slot}}"
    deploy:
      replicas: 2

networks:

  net:

运行命令:

docker network create -d overlay net
docker stack deploy -c /tmp/compose.yml my

我期望service-A单个容器将能够通过容器预定义的主机名service-B发现service-B-1, service-B-2容器。 但是,任何ping service-B-1容器中的service-A都会失败。

Docs状态:

  

主机名设置容器知道其自身的主机名。这是写的   进入/ etc / hostname,进入/ etc / hosts作为容器的名称   面向主机的IP地址,是/ bin / bash   容器将显示在其提示内。但是主机名并不容易   从容器外面看。它不会出现在docker ps或   在任何其他容器的/ etc / hosts文件中。

如何通过容器预定义的主机名实现docker swarm服务容器以服务容器通信?

唯一可行的方法是添加以下条目:

[service_B_container_1_virtual_ip] service-B-1
[service_B_container_2_virtual_ip] service-B-2

/etc/hosts个容器中的service-A

有趣的是,如果hostname未在docker-composes文件中设置,而是由docker生成的,则ping [container_id]即使在多主机docker swarm中也成功。

我期望预定义的主机名具有相同的行为。

1 个答案:

答案 0 :(得分:1)

我认为没有任何直接的方法可以做到这一点。而且我思考得越多,就应该设计不应该来完成您要问的事情。

堆栈服务的基本特性之一是,它应该以一种Docker能够互换地对待该服务中所有副本的方式进行部署。如果需要连接到各个实例,则建议不要首先将这些容器创建为服务副本,因为有 something 可以区分它们。适当的堆栈服务应能够将每个副本视为可以随时销毁和重建的临时实体,并且该操作从外部不可见。

可以在Docker网络内部执行的操作是使用服务名称引用服务实体。因此,在您的示例中,ping Service-A应该可以从堆栈中的任何容器工作,ping Service-B也可以。

服务中各个容器的名称类似

my_stack_redis.1.y1pwzeg8239yb6n6ynefs78br
my_stack_webserver.1.d6cxx8nlg7db9m2poy9wfjdyd

如果您绝对必须从容器中访问这些名称,我能想到的唯一方法是在启动时通过绑定安装在容器内部公开/var/run/docker.sock。然后,将套接字上的chmod 750作为CMD / ENTRYPOINT脚本的一部分,以便非root用户可以读取它。现在,您应该能够安装Docker CLI并使用docker network inspect查找实际服务成员的名称,然后使用jq解析它们(您可能需要将两个软件包都添加到映像中) 。但是到那时,更好的选择可能是将那些不可替代的容器分成自己的服务组。