如何在一个组合群中获得有关我们自己的信息

我有一个名为“节点”的docker集装箱,我想缩放。 该节点需要知道哪个节点实际上有多less个节点。 总数可能是一个环境variables,但目前更麻烦。

$ docker-compose scale node=100 Starting projectdir_node_1 ... done Creating and starting projectdir_node_2 ... done Creating and starting projectdir_node_3 ... done Creating and starting projectdir_node_4 ... done Creating and starting projectdir_node_5 ... done Creating and starting projectdir_node_6 ... done Creating and starting projectdir_node_7 ... done Creating and starting projectdir_node_8 ... done Creating and starting projectdir_node_9 ... done ... Creating and starting projectdir_node_99 ... done Creating and starting projectdir_node_100 ... done 

怎么projectdir_node_100现在是节点100 ? 我看到$HOSTNAME是容器的id(例如2c73136347cd ),但没有find我需要的主机名的ENVvariables。

作为参考,我docker-compose.yml

 version: '2' services: node: build: ./node/ volumes: - ./node/code/:/code:ro entrypoint: ["/bin/bash"] 

我find了未解决的如何在docker-compose scale之后通过主机名访问额外的容器? ,但我仍然不知道我是哪个容器。

我能解决这个问题的方法是使用docker api。 我使用docker-py包来访问它。

api为每个容器公开一个labels字典,并且com.docker.compose.container-numbercom.docker.compose.projectcom.docker.compose.service这两个键做了build立主机名所需的东西。

下面的代码是我现在使用的代码的简化。 你可以在Github的luckydonald / pbft / dockerus.ServiceInfos (备份在gist.github.com )find我的高级代码。

让我们分步骤解决这个问题:

0.使API可用于容器。

我们需要使socket文件可用于卷,因此在docker-compose.yml文件的卷部分添加/var/run/docker.sock:/var/run/docker.sock

 version: '2' services: node: build: . volumes: - /var/run/docker.sock:/var/run/docker.sock 

这将套接字文件映射到泊坞窗容器中。 因为我们不暴露任何套接字端口,所以我们不必担心外面的防火墙。

1.连接到API

现在我们可以连接到它。 因为我使用python,所以我使用docker-py 。

 from docker import Client # pip install docker-py cli = Client(base_url='unix://var/run/docker.sock') 

2.通过我们自己的项目名称和服务名称筛选容器,将所有容器放在同一个比例组中。 find自己

要知道我们是哪个容器,我们比较$HOSTNAME环境variables和容器Id

 import os HOSTNAME = os.environ.get("HOSTNAME") all_containers = cli.containers() # filter out ourself by HOSTNAME our_container = [c for c in all_containers if c['Id'][:12] == HOSTNAME[:12]][0] 

主机名应该是Id 12个字符,所以我们在比较时削减了id,以确保它是相等的。 our_container现在是我们的api代表。 好极了。

接下来是获得其他容器。

我们将search具有相同项目和服务名称的容器。 这样我们知道他们是我们自己的事例。

 service_name = our_container.Labels['com.docker.compose.service'] project_name = our_container.Labels['com.docker.compose.project'] filters = [ 'com.docker.compose.project={}'.format(project_name), 'com.docker.compose.service={}'.format(service_name) ] # The python wrapper has a filter function to do that work for us. containers = cli.containers(filters={'label': filters}) 

我们只需要com.docker.compose.projectcom.docker.compose.service标签与我们自己的容器相同的每个容器。

最后build立一个主机名列表

 hostname_list = list() for container in containers: project = container.Labels["com.docker.compose.project"] service = container.Labels["com.docker.compose.service"] number = container.Labels["com.docker.compose.container-number"] hostname = "{project}_{service}_{i}".format(project=project, service=service, i=number) hostname_list.append(hostname) # end for 

所以,我们得到了我们的hostname_list

我正在使用它作为一个类,caching值的一分钟: dockerus.ServiceInfos (备份在gist.github.com )