2016-09-29 5 views
3

Ich habe einen Andock-Container namens "Knoten", den ich skalieren möchte. Dieser Knoten muss wissen, welcher Knoten wie viele Knoten es tatsächlich ist. Die Summe könnte eine Umgebungsvariable sein, aber der Strom ist beunruhigender.So erhalten Sie Informationen über uns selbst in einem Compose-Cluster

$ 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 

Wie kann projectdir_node_100 jetzt ist es Knoten 100? Ich sah, dass $HOSTNAME ist die Container-ID (z. B. 2c73136347cd), aber keine ENV-Variable für den Hostnamen mit der Nummer, die ich brauche.

Als Referenz mein docker-compose.yml:

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

fand ich die ungelösten How to reach additional containers by the hostname after docker-compose scale?, aber ich weiß noch nicht, welche Behälter ich bin.

Antwort

1

Die Art, wie ich das lösen konnte, war mit dem Docker Api. Ich habe das Paket docker-py verwendet, um darauf zuzugreifen.

Die api legt einen labels Wörterbuch für jeden Behälter, und die Tasten com.docker.compose.container-number, com.docker.compose.project und com.docker.compose.service tat, was erforderlich, um die Hostnamen zu bauen.

Der Code unten ist eine vereinfachte für Code, den ich jetzt verwende. Sie können meinen erweiterten Code mit Caching und ausgefallenen Sachen finden, die bei Github um luckydonald/pbft/dockerus.ServiceInfos (Sicherung bei gist.github.com).

Lasst uns dies in Schritten angehen:

0. Machen Sie die API für den Container verfügbar.

Wir brauchen die Socket-Datei zur Verfügung, die Lautstärke zu machen, so im Volumenbereich Ihrer docker-compose.yml Datei /var/run/docker.sock:/var/run/docker.sock hinzufügen:

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

Dies bildet die Socket-Datei in den Behälter Docker. Da wir keine Socket-Ports bereitstellen, müssen wir uns keine Gedanken über Firewalls für die Außenwelt machen.

1. Verbinden Sie sich mit der API

Jetzt können wir es verbinden. Da ich Python verwende, benutze ich dafür.

2. Alle Container in derselben Staffelgruppe abrufen, indem die Container nach unserem eigenen Projektnamen und Servicenamen gefiltert werden. Finden Sie uns

Um zu wissen, welche Container wir sind, vergleichen wir die $HOSTNAME Umgebungsvariable mit dem 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] 

Der Hostname sollte 12 Zeichen des Id sein, so schneiden wir die ID, wenn es gleich wird sicher sein zu vergleichen. our_container ist jetzt die api Darstellung von uns. Yay.

Als nächstes erhalten Sie die anderen Container.

Wir suchen nach Containern, die die gleichen Projekt- und Servicenamen haben. So wissen wir, dass sie Instanzen unserer selbst sind.

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}) 

Wir wollen nur jeden Container, wo die com.docker.compose.project und com.docker.compose.service Etikett das gleiche wie unsere eigenen Containers ist.

Und schließlich eine Liste der Host-Namen
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 

So bauen, haben wir unsere hostname_list.

Ich benutze das als eine Klasse, mit Zwischenspeichern den Wert für eine Minute: dockerus.ServiceInfos (Backup bei gist.github.com)

+0

Sicherung dieser Antwort und die Code-Datei auf [gist.github.com] (https://gist.github.com/luckydonald/8e13eae89925b79ba4cce3ece9fb1955) – luckydonald

Verwandte Themen