无法从容器内部连接到本地主机连接被拒绝

时间:2018-07-20 12:41:02

标签: docker nginx ansible molecule

我目前正在使用分子测试Ansible角色。 基本上,Molecule会启动一个与Ansible兼容的容器并在其上运行角色。

为了测试容器,分子还使用Testinfra嵌入了单元测试。 python单元测试从容器内运行,因此您可以检查角色的符合性。

当我在基于Nginx的角色上工作时,单元测试之一就是发出一个curl http://localhost:80

我的确收到以下错误消息:

  

卷曲:(7)无法连接到本地主机端口80:连接被拒绝

当我:

  • 启动无业游民的机器
  • 将角色应用于Ansible
  • 通过vagrant ssh
  • 连接
  • 发出curl http://localhost命令

nginx正确回答。

因此,我相信:

  • 角色正常工作且Nginx已正确安装
  • Docker具有另一种设置网络的方式。在某种程度上,本地主机和127.0.0.1 不再相同

我的问题如下:

  1. 我正确吗?
  2. 可以克服这种差异,以便卷曲吗?

2 个答案:

答案 0 :(得分:1)

默认情况下,Docker容器在其自己的网络名称空间中启动。该名称空间包括一个单独的回送接口(127.0.0.1),该接口与主机和任何其他容器上的同一接口不同。如果要从另一个容器或通过主机上已发布的端口访问应用程序,则需要侦听所有接口(0.0.0.0),而不是回送接口。

我经常看到的另一个问题是在连接的某一层(主机或容器内部),“ localhost”名称映射到/ etc / host中的::1的IPv6值。文件,并且在该连接中的某个位置只有IPv4值有效(端口发布的位置,应用程序正在侦听或者主机或docker引擎上未启用IPv6)。因此,请确保尝试直接连接到IPv4地址127.0.0.1,以消除任何潜在的IPv6问题。

关于curl命令及其纠正方法,如果没有更多有关如何运行curl(在单独的容器中),如何运行应用程序以及如何进行卷曲的详细信息,我将无法回答。两个在网络上连接(您是否在docker中创建了一个新网络以供您的应用程序和单元测试运行)。典型的解决方案是在docker中创建一个新网络,在该网络上运行两个容器,然后通过docker包含的DNS连接到目标的容器或服务名称,例如curl http://my_app/


编辑:根据注释,如果您的应用程序和curl命令都在同一个容器中运行,那么curl http://127.0.0.1/应该可以工作。我知道curl并不需要进行任何更改,以使其可以在容器内运行而不是在VM上运行。您看到的错误很可能是由于应用程序未按预期启动和侦听端口,可能是在curl命令运行得太早的竞争条件下,或者该工具的工作原理基本假设不正确。首先更改单元测试以验证应用程序已启动并运行,并使用ps -efss -lt之类的命令在端口上进行监听。

答案 1 :(得分:0)

实际上,它与Docker和Vagrant之间的差异(即容器与VM)无关。

testInfra代码实际上是从容器/ VM外部运行的,因此subprocess.call(['curl', 'http://localhost'])失败。

为了从容器/ VM运行命令,我应该使用:

host.check_output('curl http://localhost')