Github Actions 中 Service Container 的使用

安全劍客發表於2020-12-07

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 job
  runner-job:
    # You must use a Linux environment when using service containers or container jobs
    runs-on: ubuntu-latest

    # Service containers to run with `runner-job`
    services:
      # Label used to access the service container
      redis:
        # Docker image
        image: redis:alpine
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # 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 code
    uses: 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 dependencies
    run: npm ci

  - name: Connect to Redis
    # Runs a script that creates a Redis client, populates
    # the client with data, and retrieves data
    run: 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 container
      REDIS_HOST: localhost
      # The default Redis port
      REDIS_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 job
  container-job:
    # Containers must run in Linux based operating systems
    runs-on: ubuntu-latest
    # Docker Hub image that `container-job` executes in
    container: node:10.18-jessie

    # Service containers to run with `container-job`
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis
        # Set health checks to wait until redis has started
        options: >-
          --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 code
    uses: 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 dependencies
    run: npm ci

  - name: Connect to Redis
    # Runs a script that creates a Redis client, populates
    # the client with data, and retrieves data
    run: 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 container
      REDIS_HOST: redis
      # The default Redis port
      REDIS_PORT: 6379

Sample

提供一個我目前在用的一個 service container,和上面的示例基本是類似的,有需要的可以參考一下:

name: dotnetcore

on: [push]

jobs:
  # Label of the container job
  redis-integration-test:
    # Containers must run in Linux based operating systems
    runs-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-containers
    services:
      # Label used to access the service container
      redis:
        # Docker Hub image
        image: redis:alpine
        # Set health checks to wait until redis has started
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps port 6379 on service container to the host
          - 6379:6379

    steps:
    - uses: actions/checkout@v1
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 5.0.x
    - name: dotnet info
      run: dotnet --info
    - name: build
      run: 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

相關文章