2017-08-19 5 views
3

J'essaye de mettre en place un exemple de réseau Docker avec ZeroMQ dans macOS, où le serverd.py envoie un message au clientd.py et le client l'affiche simplement en utilisant PUSH/PULL. Si je les lance à l'extérieur du conteneur, ils fonctionnent bien, mais j'ai du mal à les faire communiquer lorsqu'ils sont dans des conteneurs séparés. Il semble que mon clientd.py ne puisse pas se connecter au nom du conteneur, bien qu'il se trouve dans le même réseau de pont. J'ai essayé de remplacer le nom d'hôte avec l'adresse IP affectée pour serverd_dev_1, mais cela ne fonctionne pas non plus.ZeroMQ ne parvient pas à communiquer entre deux conteneurs Docker

Voici ma configuration:

  1. J'ai créé un nouveau réseau avec docker network create -d bridge mynet. Voici la sortie de docker network inpsect mynet:

    { 
        "Name": "mynet", 
        "Id": "cec7f8037c0ef173d9a9a66065bb46cb6a631fea1c0636876ccfe5a792f92412", 
        "Created": "2017-08-19T09:52:44.8034344Z", 
        "Scope": "local", 
        "Driver": "bridge", 
        "EnableIPv6": false, 
        "IPAM": { 
         "Driver": "default", 
         "Options": {}, 
         "Config": [ 
          { 
           "Subnet": "172.18.0.0/16", 
           "Gateway": "172.18.0.1" 
          } 
         ] 
        }, 
        "Internal": false, 
        "Attachable": false, 
        "Ingress": false, 
        "ConfigFrom": { 
         "Network": "" 
        }, 
        "ConfigOnly": false, 
        "Containers": { 
         "5fa8dc2f8059d675dfd3dc4f2e50265be99361cd8a8f2730eb273772c0148742": { 
          "Name": "serverd_dev_1", 
          "EndpointID": "3a62e82b1b34d5c08f2a9f340ff93aebd65c0f3dfde70e354819befe21422d0b", 
          "MacAddress": "02:42:ac:12:00:02", 
          "IPv4Address": "172.18.0.2/16", 
          "IPv6Address": "" 
         }, 
         "ec1e5f8c525ca8297611e02bcd3a64198fda3a07ce8ed82c0c4298609ba0357f": { 
          "Name": "clientd_dev_1", 
          "EndpointID": "a8ce6f178a225cb2d39ac0009e16c39abdd2dae02a65ba5fd073b7900f059bb8", 
          "MacAddress": "02:42:ac:12:00:03", 
          "IPv4Address": "172.18.0.3/16", 
          "IPv6Address": "" 
         } 
        }, 
        "Options": {}, 
        "Labels": {} 
    } 
    
  2. J'ai créé serverd.py et clientd.py comme celui-ci et les mettre dans des dossiers séparés avec leurs Dockerfiles et docker-compose.yml:

serverd.py:

import zmq 
import time 

context = zmq.Context() 
socket = context.socket(zmq.PUSH) 
address = "tcp://127.0.0.1:5557" 
socket.bind(address) 
print("Sending to {}...".format(address)) 
while True: 
    message = socket.send_string("Got it!") 
    print("Sent message") 
    time.sleep(1) 

clientd.py:

import zmq 

context = zmq.Context() 
socket = context.socket(zmq.PULL) 
address = "tcp://serverd_dev_1:5557" 
socket.connect(address) 
print("Listening to {}...".format(address)) 
while True: 
    message = socket.recv_string() 
    print("Client got message! {}".format(message)) 

I ont deux Dockerfiles et docker-compose.yml:

Dockerfile pour serverd.py:

FROM python:3.6 

RUN mkdir src 
ADD serverd.py /src/ 
RUN pip install pyzmq 
WORKDIR /src/ 
EXPOSE 5557 

Dockerfile pour clientd.py:

FROM python:3.6 

RUN mkdir src 
ADD clientd.py /src/ 
RUN pip install pyzmq 
WORKDIR /src/ 
EXPOSE 5557 

docker-Compose. yml pour serverd.py:

dev: 
    build: . 
    command: ["python", "-u", "./serverd.py"] 
    net: mynet 

docker-Compose pour clientd.py:

dev: 
    build: . 
    command: ["python", "-u", "./clientd.py"] 
    net: mynet 
  1. serverd.py démarre comme prévu avec docker-compose up:

Sending to tcp://127.0.0.1:5557...

  1. clientd.py ne démarrera pas comme ceci parce qu'il ne trouve pas le nom d'hôte tcp://serverd_dev_1:5557.

    Attaching to countd_dev_1 
    dev_1 | Traceback (most recent call last): 
    dev_1 | File "./countd.py", line 6, in <module> 
    dev_1 |  socket.connect(address) 
    dev_1 | File "zmq/backend/cython/socket.pyx", line 528, in zmq.backend.cython.socket.Socket.connect (zmq/backend/cython/socket.c:5971) 
    dev_1 | File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc (zmq/backend/cython/socket.c:10014) 
    dev_1 | zmq.error.ZMQError: Invalid argument 
    
  2. Si je remplace l'URI tcp://serverd_dev_1:5557 avec tcp://172.18.0.2:5557 il ne plante plus, mais il est tout simplement marche au ralenti, sans recevoir des messages du serveur. Évidemment, je fais quelque chose de mal, mais je ne suis pas tout à fait sûr de quoi exactement. J'ai l'impression d'avoir suivi la documentation de Docker le plus fidèlement possible, et je serais très reconnaissant si vous aviez des idées.

+0

Mon suspect est un docker-isolation des périphériques. Pourriez-vous définir les adresses cibles dans un format IPv4-absolute du côté ** '.bind()' ** -, comme 'address =" tcp: //172.18.0.2: 5557 "' ne pas compter sur n'importe quelle résolution de DNS et l'employant aussi comme le '.connect()' -target respectif sur le client? ** 'EXPOSE' ** semble juste pour arbitrer la gestion des ports entre la gestion des ressources 0/S de l'hôte et l'abstraction docker utilisée pour l'isolation, de sorte que le code interne (container-docker-container) doit utiliser la classe : \\ adresse: port # 'sur leur propre vision du monde (d'un point de vue interne). – user3666197

Répondre

3

Votre problème principal est que vous avez configuré votre serveur avec l'adresse tcp://127.0.0.1:5557. Parce qu'il est lié à localhost (127.0.0.1), ce socket ne sera pas visible à tout ce qui est en dehors de ce conteneur. La première chose à corriger est donc l'adresse de liaison du serveur. Considérez:

address = "tcp://0.0.0.0:5557" 

Un deuxième problème est que vous utilisez le nom serverd_dev_1 dans le client, mais il est pas clair ce serait en fait le nom de votre conteneur serverd (cela dépendra des noms de répertoire utilisé lorsque vous exécutez docker-compose up).

Le nommage est plus facile à gérer avec un seul fichier docker-compose.yaml. Par exemple, je mets les choses comme ceci:

version: "2" 

services: 
    serverd: 
    build: serverd 
    command: ["python", "-u", "./serverd.py"] 
    environment: 
     SERVER_LISTEN_URI: tcp://0.0.0.0:5557 

    clientd: 
    build: clientd 
    command: ["python", "-u", "./clientd.py"] 
    environment: 
     SERVER_CONNECT_URI: tcp://serverd:5557 

Cela lancera les deux conteneurs dans un réseau dédié (parce que c'est ce docker-Compose fait par défaut), de sorte que vous ne pas besoin de créer explicitement ou référence mynet.

Comme vous pouvez probablement déduire de ce qui précède, j'ai modifié votre code pour obtenir l'uri ZMQ à partir d'une variable d'environnement, car cela a facilité l'expérimentation. Vous pouvez trouver le docker-compose.yaml ci-dessus et le code modifié à:

Mise à jour

Si vous voulez vraiment/besoin d'avoir deux fichiers séparés docker-compose.yaml, J'ai mis à jour l'exemple pour inclure les fichiers par service. Ces exemples utilisent l'option alias pour fournir un nom par lequel le client peut contacter le serveur, quel que soit votre mise en page de répertoire local:

version: "2" 

services: 
    serverd: 
    build: . 
    command: ["python", "-u", "./serverd.py"] 
    environment: 
     SERVER_LISTEN_URI: tcp://0.0.0.0:5557 
    networks: 
     mynet: 
     aliases: 
      - serverd 

networks: 
    mynet: 
    external: True 

Cette configuration nécessite que vous créez mynet avant d'aborder les conteneurs.

+0

Avec tout le respect que je vous dois, l'O/P a posté le code sous test dès le début (** item 2 ** ci-dessus, les deux ** serverd.py ** et ** clientd.py **). Le code (après avoir correctement corrigé le '', la résolution DNS/hostname et 'IPv4-address: port #'), l'hypothèse d'un bogue dans la partie ZeroMQ échoue. – user3666197

+0

@larsks Merci pour cette réponse si complète! J'ai été confus sur deux parties: j'ai supposé depuis des exemples en utilisant la redirection de port à la machine hôte utilisée localhost, de même en utilisant le réseau docker. Deuxièmement, je pensais que Containers -> Name dans 'docker network inspect mynet' était le nom à utiliser comme nom d'hôte. Votre suggestion de combiner le docker-compose.yml a tout fait beaucoup mieux aussi. Merci d'avoir pris votre temps! –

+0

@ user3666197 On dirait que la personne qui se plaint des bugs a tiré ses commentaires, donc je vais enlever les miens aussi puisqu'ils ne sont pas vraiment pertinents pour la réponse ... – larsks