Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python ZeroMQ无法在两个Docker容器之间通信_Python_Docker_Zeromq_Configuration Files_Pyzmq - Fatal编程技术网

Python ZeroMQ无法在两个Docker容器之间通信

Python ZeroMQ无法在两个Docker容器之间通信,python,docker,zeromq,configuration-files,pyzmq,Python,Docker,Zeromq,Configuration Files,Pyzmq,我试图在macOS中设置一个Docker与ZeroMQ联网的玩具示例,其中serverd.py向clientd.py发送一条消息,客户端只需使用推/拉方式显示该消息。如果我在容器外运行它们,它们可以正常工作,但是在单独的容器内运行时,我很难让它们进行通信。似乎myclientd.py无法连接到容器名称,尽管它们位于同一网桥网络中。我尝试将主机名替换为serverd\u dev\u 1的指定ip地址,但这也不起作用 以下是我的设置: 我用docker network create-d bridge

我试图在macOS中设置一个Docker与ZeroMQ联网的玩具示例,其中
serverd.py
clientd.py
发送一条消息,客户端只需使用推/拉方式显示该消息。如果我在容器外运行它们,它们可以正常工作,但是在单独的容器内运行时,我很难让它们进行通信。似乎my
clientd.py
无法连接到容器名称,尽管它们位于同一网桥网络中。我尝试将主机名替换为
serverd\u dev\u 1
的指定ip地址,但这也不起作用

以下是我的设置:

  • 我用
    docker network create-d bridge mynet
    创建了一个新网络。以下是mynet中docker网络的输出:

    {
        "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": {}
    }
    
  • 我像这样创建了
    serverd.py
    clientd.py
    ,并将它们与dockerfile和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)
    
    FROM python:3.6
    
    RUN mkdir src
    ADD serverd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    
    dev:
      build: .
      command: ["python", "-u", "./serverd.py"]
      net: mynet
    
    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))
    
    FROM python:3.6
    
    RUN mkdir src
    ADD clientd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    
    dev:
      build: .
      command: ["python", "-u", "./clientd.py"]
      net: mynet
    
    我有两个DockerFile和docker-compose.yml:

    serverd.py的Dockerfile:

    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)
    
    FROM python:3.6
    
    RUN mkdir src
    ADD serverd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    
    dev:
      build: .
      command: ["python", "-u", "./serverd.py"]
      net: mynet
    
    clientd.py的Dockerfile:

    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))
    
    FROM python:3.6
    
    RUN mkdir src
    ADD clientd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    
    dev:
      build: .
      command: ["python", "-u", "./clientd.py"]
      net: mynet
    
    用于serverd.py的docker-compose.yml:

    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)
    
    FROM python:3.6
    
    RUN mkdir src
    ADD serverd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    
    dev:
      build: .
      command: ["python", "-u", "./serverd.py"]
      net: mynet
    
    clientd.py的docker compose:

    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))
    
    FROM python:3.6
    
    RUN mkdir src
    ADD clientd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    
    dev:
      build: .
      command: ["python", "-u", "./clientd.py"]
      net: mynet
    
  • serverd.py
    通过
    docker compose up
    按预期启动:
  • 发送到tcp://127.0.0.1:5557...

  • clientd.py
    不会像这样启动,因为它找不到主机名
    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
    
    连接到countd_dev_1
    dev_1 |回溯(最后一次最近调用):
    dev_1|文件“/countd.py”,第6行,在
    dev_1 | socket.connect(地址)
    开发人员1 |文件“zmq/backend/cython/socket.pyx”,第528行,在zmq.backend.cython.socket.connect(zmq/backend/cython/socket.c:5971)中
    开发人员1 |文件“zmq/backend/cython/checkrc.pxd”,第25行,在zmq.backend.cython.checkrc.|检查| rc(zmq/backend/cython/socket.c:10014)中
    dev_1 | zmq.error.ZMQError:参数无效
    
  • 如果我替换URI
    tcp://serverd_dev_1:5557
    tcp://172.18.0.2:5557
    它不再崩溃,但只是空转,没有从服务器接收任何消息。显然我做错了什么,但我不完全确定到底是什么。我觉得我一直在尽可能地关注Docker文档,如果您有任何想法,我将不胜感激


  • 您的主要问题是您已使用地址
    tcp://127.0.0.1:5557
    。因为它绑定到localhost(
    127.0.0.1
    ),所以该套接字对于该容器之外的任何对象都不可见。因此,首先需要修复的是服务器绑定地址。考虑:

    address = "tcp://0.0.0.0:5557"
    
    第二个问题是,您正在客户端中使用名称
    serverd_devu_1
    ,但不清楚这是否是您的serverd容器的名称(这取决于运行
    docker compose up
    时使用的目录名)

    使用单个docker-compose.yaml文件命名更易于管理。例如,我的设置如下:

    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
    
    这将在专用网络中启动这两个容器(因为docker compose默认情况下就是这样做的),因此您不需要显式地创建或引用
    mynet

    正如您可能从上面推断的那样,我修改了您的代码以从环境变量获取ZMQURI,因为这使实验更容易。您可以在以下位置找到上述docker-compose.yaml和修改后的代码:

    更新

    如果您真的想要/需要两个独立的
    docker compose.yaml
    文件,我已经更新了示例以包含每个服务文件。这些示例使用
    alias
    选项提供一个名称,客户机可以通过该名称与服务器联系,而不管您的本地目录布局如何:

    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
    

    此配置要求您在启动容器之前创建
    mynet

    我的嫌疑犯是设备的docker隔离。您是否介意在
    .bind()
    -端以IPv4绝对格式将目标地址设置为
    地址=”tcp://172.18.0.2:5557“
    不依赖任何DNS解析并将其用作客户端上相应的
    .connect()
    -目标
    EXPOSE
    似乎只是在主机0/S资源管理和用于隔离的docker抽象之间进行端口管理,因此内部(docker容器内部)代码应该根据自己的世界观(从内部人的角度)使用正确的设置
    :\\address:port#
    。恕我直言,O/P从一开始就发布了测试中的代码(上面的项目2,serverd.py和clientd.py)。代码(正确地修复了
    、DNS/主机名解析和
    IPv4地址:端口#
    )是有效的,因此关于ZeroMQ部分中存在错误的假设是不正确的。@larsks感谢您提供了如此全面的答案!我对两个部分感到困惑:我假设,因为使用端口转发到主机的示例使用localhost,所以使用docker网络也是如此。其次,我认为容器->docker network inspect mynet中的名称是用作主机名的名称。你建议合并docker-compose.yml也让一切变得更好。谢谢你花时间@user3666197看起来抱怨bug的人已经删除了他的评论,所以我也要删除我的评论,因为它们与答案并不相关…@larsks惊人的努力!作为一名码头工人新手,它确实在许多方面帮助了我。正是像你这样的人使stackoverflow成为如此惊人的资源。