从在DinD内部运行的容器访问GitLab CI服务

时间:2019-04-26 06:31:57

标签: docker gitlab gitlab-ci

我正在尝试在GitLab CI中进行持续集成,其中包括:

  • 构建docker映像
  • 运行测试
  • 将docker映像推送到注册表

那些正在执行一项任务。在进行一些需要与数据库通信的测试之前,我可以毫无问题地做到这一点。我的容器无法与已定义的Postgres服务通信。

我已经用简单的ping脚本在a public repository中重现了

image: docker:stable

services:
  - docker:dind
  - postgres:latest

job1:
  script:
    - ping postgres -c 5
    - docker run --rm --network="host" alpine:latest sh -c "ping postgres -c 5"

第一个脚本可以毫无问题地运行,但是第二个脚本因错误而失败

ping: bad address 'postgres'

我如何访问该服务?

还是应该在其他工作中运行测试?

1 个答案:

答案 0 :(得分:1)

解决方案是使用 --add-host=postgres:$POSTGRES_IP 传递作业容器中存在的 IP 地址。

要找出链接到外部容器的 postgres ip,您可以使用例如 getent hosts postgres | awk '{ print $1 }'

所以 yml 看起来像

image: docker:stable

services:
  - docker:dind
  - postgres:latest

job1:
  script:
    - ping postgres -c 5
    - docker run --rm --add-host=postgres:$(getent hosts postgres  | awk '{ print $1 }') alpine:latest sh -c "ping postgres -c 5"

要理解为什么在这种情况下连接容器的其他更常见的方法不起作用,我们必须记住我们正在尝试将嵌套容器与链接到其“父”的服务链接。像这样:

gitlab ci runner --> docker       -> my-container (alpine)
                  -> docker:dind
                  -> postgres

所以我们试图将一个容器与其“叔叔”连接起来。或者连接嵌套容器

正如@tbo 所指出的,使用 --network host 将不起作用。这可能是因为 gitlab ci 使用 --link(如 here 所述)而不是较新的 --network 来连接容器。 --link 的工作方式使得服务容器连接到作业容器,但不相互连接。所以使用主机网络不会让嵌套容器继承 postgres 主机名。

人们也可能认为使用 --link postgres:postgres 会起作用,但它也不会,因为在这种环境中 postgres 只是一个带有外部容器 ip 的主机名。这里没有容器与嵌套容器链接

因此,我们所能做的就是使用上面解释的 --add-host 手动将具有正确 ip 的主机添加到嵌套容器中。