容器如何识别一组扩展的docker-compose服务中的哪个容器? [英] How can a container identify which container it is in a set of a scaled docker-compose service?

查看:87
本文介绍了容器如何识别一组扩展的docker-compose服务中的哪个容器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 node 的码头集装箱,我想扩展到n个集装箱。
一个给定的 node 容器需要知道它在n个按比例缩放的 node 容器的集合中的哪个容器。
总数可能在一个环境变量中,但当前值更令人不安。

I have a docker container called node that I want to scale to n containers. A given node container needs to know which container it is in the set of n scaled node containers. The total could be in an environment variable, but the current is more troubling.

$ 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 ),但是没有发现ENV变量

How can projectdir_node_100 know it is node 100? I saw that $HOSTNAME is the container id (e.g. 2c73136347cd), but found no ENV variable for the hostname with number I need.

作为参考,我的 docker-compose.yml

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

我发现了尚未解决的如何达到其他目标,但是我仍然不知道我是哪个容器。

I found the unsolved How to reach additional containers by the hostname after docker-compose scale?, but I still don't know which container I am.

推荐答案

这可以通过使用Docker api来解决。

This can be solved by using the Docker api.

虽然此答案中的代码是Python,而我链接的示例是Java,但这与您的语言无关。只需将Docker API与您选择的库一起使用,或直接向Docker API套接字发出请求。

While the code in this answer is Python, and my linked example is Java, this is pretty independent of your language. Just use the Docker API with a library of your choice, or make requests directly to the Docker API socket.

我使用了 docker-py 软件包即可访问。

I used the docker-py package to access it.

该api公开了标签每个容器的字典,以及键 com.docker.compose.container-number com.docker.compose.project com.docker.compose.service 完成了构建主机名所需的工作。

The api exposes a labels dictionary for each container, and the keys com.docker.compose.container-number, com.docker.compose.project and com.docker.compose.service did what was needed to build the hostname.

下面的代码是我现在正在使用的代码的简化。
您可以在Github上的 luckydonald / pbft / dockerus.ServiceInfos(python)以及 luckydonald / pbft-java / de.luckydonald.utils.dockerus.Dockerus(java)试图在Java中执行相同的操作,但可能更难阅读,并且没有缓存。

The code below is a simplified for code I am now using. You can find my advanced code with caching and fancy stuff that at Github at luckydonald/pbft/dockerus.ServiceInfos (python) as well as a similar java version at luckydonald/pbft-java/de.luckydonald.utils.dockerus.Dockerus (java) which tries to do the same thing in java, but is probably harder to read, and has no caching.

某些事情

让我们分步解决此问题:

Lets tackle this in steps:

0。

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

We need to make the socket file available to the volume, so in the volume section of your docker-compose.yml file add /var/run/docker.sock:/var/run/docker.sock:

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

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

This maps the socket file into the docker container. Because we don't expose any socket ports, we don't have to worry about firewalls for the outside world.

1。连接到API

现在我们可以连接到它了。当我使用python时,我为此使用 docker-py

Now we can connect to it. As I am using python, I use docker-py for that.

from docker import Client  # pip install docker-py

cli = Client(base_url='unix://var/run/docker.sock')




2。通过按我们自己的项目名称和服务名称过滤容器,将所有容器归入同一比例组。

要知道我们是哪个容器,我们将 $ HOSTNAME 环境变量与容器 Id 进行比较。

To know which container we are, we compare the $HOSTNAME environment variable with the container 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表示。是的。

The hostname should be 12 characters of the Id, so we cut the id when comparing to be sure it will be equal. our_container now is the api representation of ourself. Yay.

我们将搜索具有相同项目和服务名称的容器。
这样我们就知道它们是我们自己的实例。

We will search for containers which have the same project and service names. That way we know they are instances of ourself.

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.project com.docker.compose.service 标签与我们自己的标签相同

We only want each container where the com.docker.compose.project and com.docker.compose.service label is the same as our own container's.

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

我也将其用作一个类,将值缓存一分钟:
dockerus.ServiceInfos (备份 gist.github.com

I am also using that as a class, with caching the values for a minute: dockerus.ServiceInfos (backup at gist.github.com)

这篇关于容器如何识别一组扩展的docker-compose服务中的哪个容器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆