如何使用 docker 让 CI 容器访问 Github 操作中的其他容器

问题描述 投票:0回答:1

在我们的 CICD 设置中,我们使用 github actions 来启动几个 docker 容器并执行一些依赖于这些 docker 容器的测试。

这是运行测试的工作流程:


jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      <setup steps omitted for brevity>
      - name: Test
        run: |
          docker compose --file ./docker/docker-compose.test.yml up -d
          npm run test

docker compose 文件(./docker/docker-compose.test.yml)只是一个简单的 mongodb 实例:

services:
    database:
        image: mongo:5.0.4
        # volumes:
        #   - ./db:/data/db
        ports:
            - '27017:27017'
        environment:
            - MONGO_INITDB_ROOT_USERNAME=<hidden>
            - MONGO_INITDB_ROOT_PASSWORD=<hidden>
            - MONGO_INITDB_DATABASE=<hidden>

最近,我发现我们可以使用 CI 映像来容器化我们的工具,以便在 github 操作上使用,而不是在每个工作流程运行中安装工具。

我制作了一个 CI 镜像并将其推送到 dockerhub:https://hub.docker.com/r/prosopo/ci

然后我修改了工作流程以使用 ci 映像作为容器来运行:


jobs:
  check:
    runs-on: ubuntu-latest
    container: 
        image: prosopo/ci:latest
        options: >
            --volume ${{ github.workspace }}:/repo
    steps:
      <setup steps omitted for brevity>
      - name: Test
        run: |
          docker compose --file ./docker/docker-compose.test.yml up -d
          npm run test

然而,这就是我遇到的障碍。

npm run test
运行一些 JS 测试,期望 mongodb 位于 localhost:27017。当您从主机运行它时,这是有效的。但是从容器(即 ci 容器)运行时,localhost 解析为 ci 容器,而不是发布 27017 端口的主机。我读到这是主机与容器网络。因此,我将测试调整为指向 docker-database-1:27017 (这是 mongo 容器的名称),并将 mongo 和 ci 容器添加到同一网络。

调整了 docker compose 文件:


services:
    database:
        image: mongo:5.0.4
        # volumes:
        #   - ./db:/data/db
        ports:
            - '27017:27017'
        networks:
            - pronet
        environment:
            - MONGO_INITDB_ROOT_USERNAME=<hidden>
            - MONGO_INITDB_ROOT_PASSWORD=<hidden>
            - MONGO_INITDB_DATABASE=<hidden>
networks:
    pronet:
        driver: bridge

然后在工作流程中:


jobs:
  check:
    runs-on: ubuntu-latest
    container: 
        image: prosopo/ci:latest
        options: >
            --volume ${{ github.workspace }}:/repo
    steps:
      <setup steps omitted for brevity>
      - name: Test
        run: |
          docker network connect pronet $(docker ps | grep prosopo/ci:latest | awk '{print $NF}')
          docker compose --file ./docker/docker-compose.test.yml up -d
          npm run test

Github 不允许您为 ci 容器指定

--network
arg,因此我必须在测试之前手动将其添加到网络中。

这似乎是一个笨拙的设置,因为:

  • 您必须手动将 ci 镜像添加到网络
  • 我们所有的 docker compose 文件现在都需要一个网络,ci 容器可以加入该网络来与容器通信
  • 测试现在不再运行除非您从同一网络中的容器运行。您无法从主机运行
    npm run test
    ,因为
    docker-database-1
    无法解析。 (我可以通过环境变量来解决这个问题,根据 CI 环境是否在
    docker-database-1
    localhost
    之间切换,但看起来很笨重!)
  • ci 容器的容器名称是一个随机字符串,因此每次运行我都必须对其进行 grep,这相当脆弱。

有更好的方法吗?我觉得这是一个常见的设置,我们不能成为第一个跨过这座桥的人。将我们的工具存储在 CI 映像中对于我们来说非常方便,可以避免较长的安装时间并保持一致的工具,所以我想让这项工作成功。但我们需要能够使用

localhost:27017
作为目标在本地运行测试以及在 CICD 中运行测试。

我读到我们可以使用 Github 服务来实现此目的,Github 会自动为您管理网络。但是,这会与工作流作业并行运行容器,这意味着 Docker 映像必须提前可用。在我们的另一个工作流程中,我们正在为依赖容器构建映像并运行一些不同的测试 - 服务容器在这里无法工作,因为 docker 映像在作业开始之前不可用。

docker docker-compose continuous-integration github-actions docker-network
1个回答
0
投票

如果您构建需要作为服务运行的映像,您可以将其传递给运行该服务的作业。这是一个快速原型,展示了它的工作原理:

name: service
on: workflow_dispatch

jobs:
  setup:
    runs-on: ubuntu-latest
    outputs:
      image: ${{ steps.set.outputs.image }}
    steps:
      - id: set
        run: echo "image=redis" >> "$GITHUB_OUTPUT"

  container-job:
    needs: setup
    runs-on: ubuntu-latest
    container: node:16-bullseye

    services:
      redis:
        image: ${{ needs.setup.outputs.image }}
        ports:
          - 6379:6379

    steps:
      - run: echo Running
© www.soinside.com 2019 - 2024. All rights reserved.