Github Actions 中 Service Container 的使用
Intro
之前写过一个 StackExchange.Redis
的一个扩展,测试项目依赖 redis,所以之前测试一直只是在本地跑一下,最近通过 Github Action 中的 Service Container 来通过 CI 来跑测试,分享一下如何使用 service container 来跑测试,不仅仅是 Redis,数据库等依赖也可以使用这样的方式来测试
Redis Service Container Sample
jobs:# Label of the runner jobrunner-job:# You must use a Linux environment when using service containers or container jobsruns-on: ubuntu-latest# Service containers to run with `runner-job`services:# Label used to access the service containerredis:# Docker imageimage: redis:alpine# Set health checks to wait until redis has startedoptions: >---health-cmd "redis-cli ping"--health-interval 10s--health-timeout 5s--health-retries 5ports:# Maps port 6379 on service container to the host- 6379:6379
上面是一个 redis service container 配置示例的一部分,需要注意的是使用 service container 的时候必须要使用 Linux 环境,因为 service container 的本质就是 docker run 了一个 container,通过一定的规则配置来实现在跑 CI 的环境可以访问的这个 service
上面的示例配置了一个 redis
的 service container,并将容器服务的 6379 端口映射到 host 的 6379 端口,这样 host 上的服务就可以通过 127.0.0.1:6379
/localhost:6379
访问到使用 docker 跑起来的 redis
服务(redis service container)了
steps:# Downloads a copy of the code in your repository before running CI tests- name: Check out repository codeuses: actions/checkout@v2# Performs a clean installation of all dependencies in the `package.json` file# For more information, see https://docs.npmjs.com/cli/ci.html- name: Install dependenciesrun: npm ci- name: Connect to Redis# Runs a script that creates a Redis client, populates# the client with data, and retrieves datarun: node client.js# Environment variable used by the `client.js` script to create# a new Redis client.env:# The hostname used to communicate with the Redis service containerREDIS_HOST: localhost# The default Redis portREDIS_PORT: 6379
Container Job Sample
上面的这种形式是在 host 上跑的,也就是直接在跑 CI 的服务器上跑的,有些情况下环境的配置比较麻烦的情况下也可以直接在指定的 docker 镜像为基础的 docker container 里跑 CI,需要注意的是 docker container 里跑 CI 的时候和直接在 host 上跑 CI 网络上有区别, host 可能就是直接访问 localhost
,container 访问就是 service 名称,来看下面的 container 的一个示例:
jobs:# Label of the container jobcontainer-job:# Containers must run in Linux based operating systemsruns-on: ubuntu-latest# Docker Hub image that `container-job` executes incontainer: node:10.18-jessie# Service containers to run with `container-job`services:# Label used to access the service containerredis:# Docker Hub imageimage: redis# Set health checks to wait until redis has startedoptions: >---health-cmd "redis-cli ping"--health-interval 10s--health-timeout 5s--health-retries 5
可以看到大部分是一样的,只是多了一个 container
的配置,这样实际的 CI 就是在这个 container 里执行的,创建的执行 CI 的 container 和 service container 是在同一个 network 下,可以直接通过服务名称来访问
steps:# Downloads a copy of the code in your repository before running CI tests- name: Check out repository codeuses: actions/checkout@v2# Performs a clean installation of all dependencies in the `package.json` file# For more information, see https://docs.npmjs.com/cli/ci.html- name: Install dependenciesrun: npm ci- name: Connect to Redis# Runs a script that creates a Redis client, populates# the client with data, and retrieves datarun: node client.js# Environment variable used by the `client.js` script to create a new Redis client.env:# The hostname used to communicate with the Redis service containerREDIS_HOST: redis# The default Redis portREDIS_PORT: 6379
Sample
提供一个我目前在用的一个 service container,和上面的示例基本是类似的,有需要的可以参考一下:
name: dotnetcoreon: [push]jobs:# Label of the container jobredis-integration-test:# Containers must run in Linux based operating systemsruns-on: ubuntu-latest# # Docker image that `job` executes in# container: mcr.microsoft.com/dotnet/sdk:5.0# Service containers to run with `container-job`# https://docs.github.com/en/free-pro-team@latest/actions/guides/creating-redis-service-containersservices:# Label used to access the service containerredis:# Docker Hub imageimage: redis:alpine# Set health checks to wait until redis has startedoptions: >---health-cmd "redis-cli ping"--health-interval 10s--health-timeout 5s--health-retries 5ports:# Maps port 6379 on service container to the host- 6379:6379steps:- uses: actions/checkout@v1- name: Setup .NET Coreuses: actions/setup-dotnet@v1with:dotnet-version: 5.0.x- name: dotnet inforun: dotnet --info- name: buildrun: bash build.sh --target=test
CI 执行日志:
从日志上我们可以看出来比普通的 CI 执行会多出两个步骤,一个是初始化 container,一个是清理 container
完整的CI 日志可以在这里看到:https://github.com/WeihanLi/WeihanLi.Redis/runs/1400006789?check_suite_focus=true
More
虽然我的场景是 redis,但是不仅仅是 redis,很多应用外的依赖比如说数据库,甚至MQ等都是可以通过 service container 来做一个完善的集成测试,没有尝试过的快去试试吧~~
References
https://docs.github.com/en/free-pro-team@latest/actions/guides/about-service-containers
https://docs.github.com/en/free-pro-team@latest/actions/guides/creating-redis-service-containers
https://github.com/WeihanLi/WeihanLi.Redis/blob/dev/.github/workflows/dotnetcore.yml