在我们的 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,因此我必须在测试之前手动将其添加到网络中。
这似乎是一个笨拙的设置,因为:
npm run test
,因为 docker-database-1
无法解析。 (我可以通过环境变量来解决这个问题,根据 CI 环境是否在 docker-database-1
和 localhost
之间切换,但看起来很笨重!)有更好的方法吗?我觉得这是一个常见的设置,我们不能成为第一个跨过这座桥的人。将我们的工具存储在 CI 映像中对于我们来说非常方便,可以避免较长的安装时间并保持一致的工具,所以我想让这项工作成功。但我们需要能够使用
localhost:27017
作为目标在本地运行测试以及在 CICD 中运行测试。
我读到我们可以使用 Github 服务来实现此目的,Github 会自动为您管理网络。但是,这会与工作流作业并行运行容器,这意味着 Docker 映像必须提前可用。在我们的另一个工作流程中,我们正在为依赖容器构建映像并运行一些不同的测试 - 服务容器在这里无法工作,因为 docker 映像在作业开始之前不可用。
如果您构建需要作为服务运行的映像,您可以将其传递给运行该服务的作业。这是一个快速原型,展示了它的工作原理:
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