在dind中运行docker-compose时Docker容器拒绝通信 - Gitlab CI/CD

Posted

技术标签:

【中文标题】在dind中运行docker-compose时Docker容器拒绝通信 - Gitlab CI/CD【英文标题】:Docker containers refuse to communicate when running docker-compose in dind - Gitlab CI/CD 【发布时间】:2021-06-07 13:26:42 【问题描述】:

我正在尝试在 Gitlab CI/CD 中设置一些集成测试 - 为了运行这些测试,我想使用 Gitlab 运行器和 docker-compose up 重建我的系统(几个链接的容器)。我的系统是由几个通过mqtt相互通信的容器和一个被其他容器查询的InfluxDB容器组成的。

我已经设法让跑步者实际执行 docker-compose up 并创建所有相关容器。这是我的 .gitlab-ci.yml 文件:

    image: docker:19.03

    variables:
      DOCKER_DRIVER: overlay2
      DOCKER_TLS_CERTDIR: "/certs"

    services:
      - name: docker:19.03-dind
        alias: localhost

    before_script:
      - docker info

    integration-tests:
      stage: test
      script:
        - apk add --no-cache docker-compose
        - docker-compose -f "docker-compose.replay.yml" up -d --build
        - docker exec moderator-monitor_datareplay_1 bash -c 'cd src ; python integration_tests.py'

如您所见,我正在安装 docker-compose,在我的配置 yml 文件上运行 compose,然后从其中一个容器中执行我的集成测试。当我在本地系统上运行最后一行时,集成测试按预期运行;然而,在 CI/CD 环境中,所有测试都会抛出一些ConnectionRefusedError: [Errno 111] Connection refused 错误。运行 docker-compose ps 似乎显示所有相关容器都正常运行。

我发现问题源于每次一个容器尝试通过self.localClient = InfluxDBClient("influxdb", 8086, database = "replay")client.connect("mosquitto", 1883, 60) 之类的行与另一个容器进行通信。这在我的本地 docker 环境中运行良好,因为地址名称解析为正在运行的其他容器,但似乎在这个 Docker-in-Docker 设置中产生了问题。有没有人有什么建议?这个dind环境中的容器有不同的名字吗?

还值得一提的是,这可能是我的 docker-compose.yml 文件未正确配置以启动健康容器的问题。 docker-compose ps 表示它们已启动,但有没有更好的方法来检查它们是否正常运行?这是我的 docker-compose 文件的摘录:

services:
    datareplay:
      networks:
        - web
        - influxnet
        - brokernet
      image: data-replay
      build:
        context: data-replay
      volumes:
        - ./data-replay:/data-replay

    mosquitto:
      image: eclipse-mosquitto:latest
      hostname: mosquitto
      networks:
        - web
        - brokernet

networks:
  web:
  influxnet:
    internal: true
  brokernet:
    driver: bridge
    internal: true

【问题讨论】:

【参考方案1】:

出现此错误的原因有几种可能:

    Docker 19.03-dind is known to be problematic and unable to create networks when using services without a proper TLS setup 上的一个错误,您是否正确设置了带有 TLS 证书的 Gitlab Runner?我注意到您在您的gitlab-ci.yml 上使用"/certs",您是否安装了您的跑步者以共享存储证书的卷?

    如果您的 Gitlab Runner 未以特权权限运行或未正确配置为使用远程计算机的网络套接字,您将无法创建网络。统一您的网络以在 CI/CD 环境中运行的一个简单解决方案是使用this docker-compose 后跟this script 配置您的机器。 (Source) 它将设置一个本地网络,您可以在其中使用桥接网络驱动程序的网络中的主机名在容器之间进行通信。

    当您执行这部分脚本时,gitlab-ci.yml 也存在问题:

    services:
      - name: docker:19.03-dind
        alias: localhost 
    integration-tests:
      stage: test
      script:
        - apk add --no-cache docker-compose
        - docker-compose -f "docker-compose.replay.yml" up -d --build
        - docker exec moderator-monitor_datareplay_1 bash -c 'cd src ; python integration_tests.py'
    

您将 docker 主机名重命名为 localhost,但您从不使用它,而是直接键入以使用图像中的 dockerdocker-compose,将它们绑定到与创建的网络不同的网络集由 Gitlab 自动生成。

让我们试试这个解决方案(虽然我现在无法测试它,所以如果它不能立即起作用,我深表歉意):

gitlab-ci.yml

image: docker/compose:debian-1.28.5 # You should be running as a privileged Gitlab Runner
services:
  - docker:dind
integration-tests:
  stage: test
  script:
    #- apk add --no-cache docker-compose
    - docker-compose -f "docker-compose.replay.yml" up -d --build
    - docker exec moderator-monitor_datareplay_1 bash -c 'cd src ; python integration_tests.py'

docker-compose.yml

services:
  datareplay:
    networks:
      - web
      - influxnet
      - brokernet
    image: data-replay
    build:
      context: data-replay
  # volumes: You're mounting your volume to an ephemeral folder, which is in the CI pipeline and will be wiped afterwards (if you're using Docker-DIND)
   #  - ./data-replay:/data-replay
  mosquitto:
    image: eclipse-mosquitto:latest
    hostname: mosquitto
    networks:
      - web
      - brokernet

networks:
  web: # hostnames are created automatically, you don't need to specify a local setup through localhost
  influxnet:
  brokernet:
    driver: bridge #If you're using a bridge driver, an overlay2 doesn't make sense
  

这两个命令都会将 Gitlab Runner 安装为 Docker 容器,而无需手动配置它们以允许在您的项目上进行套接字绑定。

(1)

docker run --detach --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest

然后(2)

docker run --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register --non-interactive --description "monitoring cluster instance" --url "https://gitlab.com" --registration-token "replacethis" --executor "docker"  --docker-image "docker:latest" --locked=true  --docker-privileged=true --docker-volumes /var/run/docker.sock:/var/run/docker.sock 

记得在 (2) 命令中更改您的令牌。

【讨论】:

非常感谢您的回复。我是 Gitlab CI/CD 的新手,所以我不明白你的全部答案。我完全按照“配置 TLS”下about.gitlab.com/blog/2019/07/31/… 中的步骤创建了一个具有特权权限的运行器。我不确定我是否将 Gitlab Runners 理解为您概述的 Docker 容器步骤。在我的 CI/CD 工作中,我注意到我的网络已成功创建。我还发现我可以 ping 例如CI/CD 工作期间数据重放的蚊子!对我来说,这表明网络已启动,但配置不正确? 我提到的 ping 步骤可以添加到我的 gitlab-ci.yml 文件:docker exec moderator-monitor_datareplay_1 bash -c 'ping -c 3 mosquitto',它的工作原理是:--- mosquitto ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 35ms。但是,当我在 python 中使用我的 mqtt 客户端连接到 mqtt 代理容器时,我仍然收到连接被拒绝的错误。 好的,最后的评论。我运行了你的两个命令 - 当我包含 -v /var/run/docker.sock:/var/run/docker.sock 时,我在这个问题中得到错误 gitlab.com/gitlab-org/gitlab-runner/-/issues/… 。如果我根据链接删除 --docker-privileged,它会抱怨 root 权限。基本上,可能配置的每一种排列都会在管道中的某个点导致一些错误。

以上是关于在dind中运行docker-compose时Docker容器拒绝通信 - Gitlab CI/CD的主要内容,如果未能解决你的问题,请参考以下文章

使用alpine的docker镜像下 dind 的方式安装dotnet core 的一个非dockerfile的方法

Gitlab-runner dind 导致错误:作业失败(系统故障):来自守护进程的错误响应:OCI 运行时创建失败:container_linux.go:380:

[转帖]Docker里运行Docker docker in docker(dind)

docker-in-docker (dind) 服务在 gitlab ci 中的作用

Docker-Compose API 调用和端点容器化

GitLab Runner Docker Executor 中的缓存层 - 长时间 DinD 容器