0

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

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

当我从事基于 Nginx 的角色时,其中一个单元测试只是发出一个curl http://localhost:80

我确实收到以下错误消息作为响应:

curl: (7) 无法连接到 localhost 端口 80:连接被拒绝

当我:

  • 启动 Vagrant 机器
  • 使用 Ansible 应用角色
  • 通过连接vagrant ssh
  • 发出curl http://localhost命令

nginx 正确回答。

因此,我认为:

  • 角色工作正常,Nginx 安装正确
  • Docker 有一种不同的方式来设置网络。在某种程度上, localhost 和 127.0.0.1不再相同了

我的问题如下:

  1. 我对么?
  2. 可以克服这种差异,以便卷曲起作用吗?
4

2 回答 2

1

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

我经常看到的另一个问题是在连接的某个层(主机或容器内部),“localhost”名称映射到::1/etc/host 文件中的 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可以让它在容器内部而不是在虚拟机上工作。您看到的错误可能是由于应用程序未按预期启动和监听端口,可能是 curl 命令运行过快的竞争条件,或者工具工作方式的基本假设不正确。首先更改单元测试以验证应用程序是否已启动并正在运行,并使用 和 之类的命令侦听ps -ef端口ss -lt

于 2018-07-20T14:48:05.073 回答
0

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

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

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

host.check_output('curl http://localhost')
于 2018-07-23T14:41:29.990 回答