首页 > 解决方案 > 如何在 Mac 上连接同一网络上的容器?

问题描述

我很难将我们的scrapy调度程序spiderkeeper连接到我本地Mac环境上的scrapyd。

两种服务都位于同一网络上的不同容器中。

Spiderkeeper 使用该SERVERS变量连接到我们的scrapyd服务器,但连接被拒绝。

当 SSH 进入 spiderkeeper 并运行curl -v scrapyd:6800时,容器拒绝连接。

真正奇怪的是,当我通过 SSH 连接到scrapyd容器并运行curl -v spiderkeeper:5000时,我得到了响应,当我们将相同的设置部署到 kubernetes 时,容器可以正常通信,但对于本地目的,这是一场噩梦。

这是docker-compose.yaml

version: '3'

services:
  scrapyd:
    build: .
    ports:
      - "6800:6800"
    depends_on:
      - spiderkeeper

  spiderkeeper:
    image: <our_spiderkeeper_image>
    ports:
      - "5000:5000"
    environment:
      SERVERS: "scrapyd:6800"

我在本地缺少什么?

标签: macosdockerscrapydocker-compose

解决方案


容器之间通信的要求是将容器放在同一个 docker 网络上,你的应用程序监听所有接口,客户端使用容器名称或服务别名和容器端口进行通信(而不是主机发布的端口)。

对于共享网络,docker compose yaml v2 及更新版本默认为您提供此功能(您只需手动定义网络即可覆盖此行为)。这里没什么可做的。

对于客户端连接,您正在尝试与服务别名和容器端口进行通信,因此该部分也是正确的。


我们看不到应用程序在所有接口上都正确侦听。我首选的故障排除方法涉及运行调试容器:

docker run -it --rm --net container:${container_id} nicolaka/netshoot netstat -lnt

以上是您的${container_id}scrapyd 容器 ID 或名称。您应该看到一行:

0.0.0.0:6800
:::6800

相反,如果您看到一行:

127.0.0.1:6800
::1:6800

然后您的应用程序正在侦听不受支持的环回接口。您需要0.0.0.0在应用程序配置中重新配置它。

如果你没有看到这些,那么你的应用程序根本没有在网络上监听,是时候开始调试应用程序、挖掘日志等了。


最后要调整的一件事是删除 docker-compose 文件中服务之间的依赖关系。这种依赖并不能解决您希望它解决的所有问题,如果您迁移到 swarm 模式,它根本不起作用。相反,最佳实践是将您的客户端应用程序配置为轮询远程服务以使其可用,如果在适当的超时内没有发生这种情况,则正常失败。很容易出现竞争条件,即 docker 在第一个服务完成启动并正在侦听端口之前启动您的第二个服务,从而导致连接被拒绝。(我怀疑这是问题,因为您描述了手动登录,大概是在应用程序有足够的时间启动之后。)

另请参阅有关 depends_on 的 docker 文档中的此注释,了解我建议反对它的原因:

使用depends_on时有几点需要注意:

  • 在启动 web 之前,depends_on 不会等待 db 和 redis “准备好” - 仅在它们启动之前。如果您需要等待服务准备好,请参阅控制启动顺序以获取有关此问题的更多信息以及解决该问题的策略。

  • 版本 3 不再支持depends_on 的条件形式。

  • 在使用版本 3 Compose 文件以 swarm 模式部署堆栈时,将忽略 depends_on 选项。


推荐阅读