使用GitHub Actions进行Docker镜像的缓存与恢复(使用actions/cache@v2)

使用 GitHub Actions 的工作流程来使用 Docker。但是,每次进行调试或者尝试和错误时需要拉取基础镜像或者构建镜像,这样会导致我担心免费配额的费用(每小时的 API 请求限制)。然而,尝试使用 actions/cache@v2 来缓存镜像时,由于权限问题,无法将 /var/lib/docker/ 目录缓存起来。如果可能的话,我不想使用 root 权限。

這是為符合以下任何一項的讀者撰寫的文章:

GitHub 公式の actions/cache@v2 アクションだけでキャッシュ処理を完結させたい。
Docker Hub や GitHub などのコンテナ・レジストリにキャッシュ目的で push pull したくない。
ベース・イメージが重いのでキャッシュしておきたい(無駄な docker pull を避けたい)
ビルドに時間がかかるのでキャッシュして再利用したい。
高速化だけでなく、外部への無駄な通信を抑えて GitHub や API のリクエスト負荷を下げたい。

简而言之,今北産業。

    1. actions/cache@v2 是一个在 GitHub 上进行指定目录缓存和恢复的操作。

docker save docker load 是用于保存和加载指定 Docker 镜像的命令。
通过应用上述两个操作,我们可以将 Docker 镜像保存在缓存目录中,它将自动帮助我们进行恢复。

总结一下(关于理解actions/cache@v2缓存的要点)

师傅,请给我整瓶

https://github.com/KEINOS/go-totp/blob/main/.github/workflows/unit-tests.yml

上記は、キャッシュ用の key(キャッシュ ID)として、複数ファイルから 1 つのハッシュ値を取得するアクションで得られた値を利用しています。つまり、指定したファイルのいずれかに 1 ビットでも変更があると key が変わります。仕組みは後述。
キャッシュがある場合は、キャッシュから Docker コンテナのイメージを読み込み、コンテナ上でテストを実行します。
キャッシュがない場合は、Docker コンテナのイメージを作成し、テストが全てパスしたら、キャッシュ・ディレクトリにイメージとしてアーカイブします。

师傅,这里面放了什么?

以下是一个示例,将检出的存储库挂载到具备测试执行环境的容器中,并运行测试脚本(hogefuga.sh)。

在这个例子中,如果跨越了一个月或者Dockerfile被修改了,缓存将被重新创建。这是因为使用了Dockerfile的哈希值和日期来生成”缓存ID”。另外,如果缓存空间超过了5GB,旧的缓存将被删除。

需要注目的地方有两个。

    1. 如果存在缓存,则在 docker load 中加载以 tar 包输出的镜像的地方。

 

    如果不存在缓存,则在构建 Docker 镜像并将其以 tar 包输出并缓存的地方。
name: "Sample Workflow"
on: [push]

env:
  # Docker run する際のコンテナにリポジトリをマウントする先のパス
  PATH_MOUNT: /workspaces/myapp
  # Docker イメージの tar アーカイブ出力先のパス
  PATH_CACHE: /tmp/docker-img-arch

jobs:
  Tests:
    runs-on: ubuntu-latest
    steps:
      # リポジトリの読み込み(fetch-depth=1)
      - name: Check out repo under workspace
        uses: actions/checkout@v2

      # キャッシュ ID の作成(イメージのハッシュと日付から作成。Windows 非互換。次項を参照)
      - name: Create image tag
        id: imagetag
        run: |
          : # Dockerfile からハッシュ値を作成
          HASH_IMAGE=${{ hashFiles('./Dockerfile') }}
          : # 日付と 7 文字のハッシュ値で合計 13 文字の ID を作成
          VARIANT=$(TZ=UTC-9 date '+%Y%m')${HASH_IMAGE:0:7}
          : # イメージのタグを作成
          NAME_IMAGE=myTestImage
          TAG="${NAME_IMAGE}:${VARIANT}"
          : # キャッシュする tar アーカイブ名とパスの設定
          NAME_TAR="${NAME_IMAGE}.${VARIANT}.tar"
          PATH_TAR=${{ env.PATH_CACHE }}"/${NAME_TAR}"
          : # 変数を他の run でも使えるように output
          echo "::set-output name=TAG::${TAG}"
          echo "::set-output name=PATH_TAR::${PATH_TAR}"

      # この Workflow が正常に終了したら path をキャッシュ。
      # key が存在する場合、ついでに path にリストアする。
      - name: Enable cache
        id: cache
        uses: actions/cache@v2
        with:
          path: ${{ env.PATH_CACHE }}
          key: ${{ steps.imagetag.outputs.TAG }}

      # キャッシュがある場合は tar をロードしてイメージ一覧に追加
      - name: Load Docker image if exists
        if: steps.cache.outputs.cache-hit == 'true'
        run: docker load --input ${{ steps.imagetag.outputs.PATH_TAR }}

      # キャッシュがない場合は Docker イメージをビルド後、tar アーカイブをキャッシュ先に保存
      - name: Build Docker image and save
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          : # キャッシュディレクトリを作成
          mkdir -p ${{ env.PATH_CACHE }}
          : # 安定したビルドのためにベース・イメージを pull しておく(オプション)
          docker pull mybaseimage:latest
          : # イメージのビルド
          docker build -f './.devcontainer/Dockerfile' -t ${{ steps.imagetag.outputs.TAG }} .
          : # イメージのキャッシュ(tar をキャッシュ・ディレクトリに出力)
          docker save --output ${{ steps.imagetag.outputs.PATH_TAR }} ${{ steps.imagetag.outputs.TAG }}

      # 本処理
      # イメージからコンテナを起動してテスト(entrypoint.sh)を実行
      - name: Run tests for both Go and Shell Script
        run: |
          : # コンテナ内のスクリプトのパスを作成(マウントポイントから見たパス)
          path_entrypoint=${{ env.PATH_MOUNT }}/path/to/hogefuga.sh
          : # 実行
          docker run -u root -v "$(pwd)":${{ env.PATH_MOUNT }} -w ${{ env.PATH_MOUNT }} ${{ steps.imagetag.outputs.TAG }} "$path_entrypoint"

      # その他の処理(例えばカバレッジのアップデート)
      - name: Upload coverage
        uses: codecov/codecov-action@v1
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

我试图将缓存ID(文件的哈希化)部分泛化。

上述的示例是指运行者(用于执行 GitHub Actions 的操作系统/平台)仅限于 Linux 和 macOS。由于缓存 ID 的创建部分不兼容 Windows 平台,因此此示例不包括 Windows。

如果您希望在Win、Mac和Linux平台上都能够缓存,您可以使用我为创建通用缓存ID的GitHub Actions创建的工具进行缓存。

File Hash for Cache | Actions | Marketplace @ GitHub

根据这篇文章的内容,我们将其适配到了Windows系统,以便能够清晰地记录。

举个例子,以下是在多个Go版本中对Go语言的包进行单元测试,并使用PHP和Python验证Go程序的输出结果的测试。

每个人都在使用Docker Compose在容器上进行测试,但都被缓存了。

# Unit testing on vaious Go versions, such as Go 1.18 and later.
# It will test the generated password hash verifying with PHP and Python.
#
# This workflow caches images built with Docker and docker-compose to speed up its execution.
name: UnitTests

on:
  workflow_dispatch:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  PATH_CACHE: /tmp/docker-img-arch

jobs:
  go:
    name: Run tests on Go via container
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v3

      - name: Create image tag from file hash
        uses: KEINOS/gh-action-hash-for-cache@main
        id: imagetag
        # Udate the hash if any file in the path has changed or the month has changed.
        with:
          path: |
            ./go.mod
            ./go.sum
            ./docker-compose.yml
            ./.github/Dockerfile
            ./.github/workflows/unit-tests.yml
          variant: $(TZ=UTC-9 date '+%Y%m')

      - name: Enable Cache
        id: cache
        uses: actions/cache@v3
        with:
          path: ${{ env.PATH_CACHE }}
          key: ${{ steps.imagetag.outputs.hash }}

      - name: Load cached Docker images if any
        if: steps.cache.outputs.cache-hit == 'true'
        run: |
          docker load --input ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}/go-totp_v1_18_1.tar
          docker load --input ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}/go-totp_v1_19_1.tar
          docker load --input ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}/go-totp_latest_1.tar

      - name: Pull base images if no-cache
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          : # Pull images one-by-one for stability
          docker pull golang:1.18-alpine
          docker pull golang:1.19-alpine
          docker pull golang:alpine

      - name: Build Docker images if no-cache
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          docker-compose build

      - name: Save/export built images to cache dir if no-cache
        if: steps.cache.outputs.cache-hit != 'true'
        run: |
          mkdir -p ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}
          docker save --output ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}/go-totp_v1_18_1.tar go-totp_v1_18:latest
          docker save --output ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}/go-totp_v1_19_1.tar go-totp_v1_19:latest
          docker save --output ${{ env.PATH_CACHE }}/${{ steps.imagetag.outputs.hash }}/go-totp_latest_1.tar go-totp_latest:latest

      - name: Run tests on Go 1.18
        run: docker-compose run v1_18
      - name: Run tests on Go 1.19
        run: docker-compose run v1_19
      - name: Run tests on latest Go
        run: docker-compose run latest

github.com/KEINOS/go-totp @ GitHub より

广告
将在 10 秒后关闭
bannerAds