私のToDo Appには、Docker Composeを使ってフロントエンドとバックエンドの両方でnpm run testを実行するGitHub Actionsが あります。以前はイメージをビルドしてからテストを実行するのに4分48秒かかっていましたが、buildxキャッシュバックエンドを使うことで、2分18秒にまで短縮されました。レイテンシは2:30短縮され、パフォーマンスは2倍以上向上しました(関連するプルリクエスト)。この記事では、キャッシュの恩恵を受けるために追加できる簡単な手順を紹介します。
TL;DR
以下の2つのステップを追加します:
--- snip ---
jobs:
  test_api:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
+      - uses: docker/setup-buildx-action@v2
+
+      - name: Build the backend image with cache
+        uses: docker/build-push-action@v4
+        with:
+          load: true
+          context: backend
+          file: backend/Dockerfile.dev
+          cache-from: type=gha,scope=$GITHUB_REF_NAME-backend-dev
+          cache-to: type=gha,scope=$GITHUB_REF_NAME-backend-dev,mode=max
      - name: Start backend
        run: docker compose -f docker-compose-dev.yml -f docker-compose-test-single.yml up -d backend
      - name: Run test
        run: docker compose -f docker-compose-dev.yml exec -T backend npm test -- --watchAll=false
  test_frontend:
    --- snip ---
解説
docker/setup-buildx-actionはbuildxビルダーのインスタンスをセットアップし、次のdocker`コマンドで使用します。
docker/build-push-actionでは3つのオプションが重要です: load、cache-from、cache-to
- load
はビルドしたイメージを "buildx の世界" から "docker の世界" にロードし、後続のdockerコマンドがビルドしたイメージを使用できるようにします。 このオプションがない場合、次のdocker compose up` コマンドはイメージを再度ビルドしてしまいます。なぜなら、ビルド結果は buildx に含まれており、docker には公開されていないからです。 - cache-from
オプションは複数のtypeを受け付けます。その他にも、registry(コンテナレジストリからキャッシュをロードする) やlocal` (ローカルファイルシステムからキャッシュをロードする) などのタイプを指定できます。 - cache-to
オプションはcache-fromと似ていますが、modeという重要なオプションも使用できます。modeをmaxに設定すると、ビルドされたイメージの各レイヤーがキャッシュされ、minモードでは最終結果のみがキャッシュさ れます。 
私の場合、frontend と backend の両方を一つの GitHub Actions でビルドしています。そのため、cache-from と cache-to に scope オプションを追加して、これらのキャッシュを区別しています。
YAMLファイル全体
name: Run tests with Docker-Compose and Makefile
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
  push:
    branches:
      - main
jobs:
  test_frontend:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - uses: docker/setup-buildx-action@v2
        with:
          driver: docker-container
      - name: Build the [frontend] image with cache
        uses: docker/build-push-action@v4
        with:
          load: true
          context: frontend
          file: frontend/Dockerfile.dev
          tags: |
            frontend-test
          cache-from: type=gha,scope=$GITHUB_REF_NAME-frontend-dev
          cache-to: type=gha,scope=$GITHUB_REF_NAME-frontend-dev,mode=max
      - name: Run test
        run: docker run --rm frontend-test npm test -- --watchAll=false
  test_api:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - uses: docker/setup-buildx-action@v2
        with:
          driver: docker-container
      - name: Build the [api] image with cache
        uses: docker/build-push-action@v4
        with:
          load: true
          context: api
          file: api/Dockerfile.dev
          cache-from: type=gha,scope=$GITHUB_REF_NAME-api-dev
          cache-to: type=gha,scope=$GITHUB_REF_NAME-api-dev,mode=max
      - name: Start api
        run: docker compose -f docker-compose-dev.yml -f docker-compose-test-single.yml up -d --remove-orphans api
      - name: Run test
        run: docker compose -f docker-compose-dev.yml exec -T api npm test -- --watchAll=false
さいごに
GitHub Actionsに数行追加するだけですが、キャッシュの効果は絶大でした。 本記事が日頃の開発に役立てば幸いです。
