メインコンテンツまでスキップ

GitHub ActionsのDocker Composeをbuildxのキャッシュを使って高速化する

· 約4分

私の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つのオプションが重要です: loadcache-fromcache-to

  • loadはビルドしたイメージを "buildx の世界" から "docker の世界" にロードし、後続のdockerコマンドがビルドしたイメージを使用できるようにします。 このオプションがない場合、次のdocker compose up` コマンドはイメージを再度ビルドしてしまいます。なぜなら、ビルド結果は buildx に含まれており、docker には公開されていないからです。
  • cache-fromオプションは複数のtype を受け付けます。その他にも、registry(コンテナレジストリからキャッシュをロードする) やlocal` (ローカルファイルシステムからキャッシュをロードする) などのタイプを指定できます。
  • cache-toオプションはcache-fromと似ていますが、mode という重要なオプションも使用できます。modemax に設定すると、ビルドされたイメージの各レイヤーがキャッシュされ、min モードでは最終結果のみがキャッシュさ れます。

私の場合、frontendbackend の両方を一つの GitHub Actions でビルドしています。そのため、cache-fromcache-toscope オプションを追加して、これらのキャッシュを区別しています。

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に数行追加するだけですが、キャッシュの効果は絶大でした。 本記事が日頃の開発に役立てば幸いです。

参考