• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

python - ZeroMQ 无法在两个 Docker 容器之间进行通信

[复制链接]
菜鸟教程小白 发表于 2022-8-3 10:10:34 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在尝试在 macOS 中使用 ZeroMQ 设置 Docker 网络的玩具示例,其中 serverd.pyclientd.py 发送消息客户端简单地使用 PUSH/PULL 显示它。如果我在容器外运行它们,它们可以正常工作,但是在单独的容器中运行时,我无法让它们进行通信。好像是我的 clientd.py尽管它们在同一个网桥网络中,但无法连接到容器名称。我尝试用为 serverd_dev_1 分配的 IP 地址替换主机名,但这也不起作用。

这是我的设置:

  • 我用 docker network create -d bridge mynet 创建了一个新网络.这是 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": {}
    }
    
  • 我创建了 serverd.pyclientd.py像这样把它们连同它们的 Dockerfiles 和 docker-compose.yml 放在单独的文件夹中:

  • 服务器.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)
    

    客户端.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))
    

    我有两个 Dockerfiles 和 docker-compose.yml:

    serverd.py 的 Dockerfile:
    FROM python:3.6
    
    RUN mkdir src
    ADD serverd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    

    clientd.py 的 Dockerfile:
    FROM python:3.6
    
    RUN mkdir src
    ADD clientd.py /src/
    RUN pip install pyzmq
    WORKDIR /src/
    EXPOSE 5557
    

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

    clientd.py 的 docker-compose:
    dev:
      build: .
      command: ["python", "-u", "./clientd.py"]
      net: mynet
    
  • serverd.py按预期启动 docker-compose up :
  • Sending to 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
    
  • 如果我替换 URI tcp://serverd_dev_1:5557tcp://172.18.0.2:5557它不再崩溃,但它只是空闲而没有从服务器接收任何消息。显然我做错了什么,但我不完全确定到底是什么。我觉得我一直在尽可能密切地关注 Docker 文档,如果您有任何想法,我将不胜感激。


  • Best Answer-推荐答案


    您的主要问题是您已使用地址 tcp://127.0.0.1:5557 配置您的服务器。 .因为它绑定(bind)到 localhost ( 127.0.0.1 ),所以该套接字不会对该容器之外的任何内容可见。因此,您需要修复的第一件事是服务器绑定(bind)地址。考虑:

    address = "tcp://0.0.0.0:5557"
    

    第二个问题是您使用的名称 serverd_dev_1在客户端中,但不清楚这实际上是您的服务器容器的名称(这取决于运行 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 .

    正如您可能从上面推断出的那样,我修改了您的代码以从环境变量中获取 ZMQ uri,因为这使实验更容易。您可以在以下位置找到上述 docker-compose.yaml 和修改后的代码:
  • https://github.com/larsks/so-example-jimmyc

  • 更新

    如果您真的想要/需要有两个单独的 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在提起容器之前。

    关于python - ZeroMQ 无法在两个 Docker 容器之间进行通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45772053/

    回复

    使用道具 举报

    懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关注0

    粉丝2

    帖子830918

    发布主题
    阅读排行 更多
    广告位

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap