技術(tech)

GitHub ActionsでのECRキャッシュマニフェスト活用術

はじめに

DockerビルドでのCIパイプラインが遅いと感じたことはありませんか?特に大規模なプロジェクトやマイクロサービスアーキテクチャでは、毎回のビルドに数十分かかることも珍しくありません。本記事では、最近AWSがサポートを開始したECRキャッシュマニフェストを活用して、ビルド時間を大幅に短縮する方法を紹介します。

技術スタック:Docker、AWS ECR、GitHub Actions

対象とする読者

  • GitHub ActionsやCircleCIなどのCIツールを使用している方
  • AWSのECRを利用している方
  • Dockerビルドの高速化に興味がある方

背景

私たちのプロジェクトでは、GitHub ActionsでDockerイメージをビルドしていますが、依存関係のインストールやアセットのコンパイルに時間がかかり、CIの実行時間が長くなっていました。特に問題だったのは、毎回のビルドで同じ依存関係を再インストールしていることでした。

CI環境では毎回新しいコンテナで実行されるため、通常のDockerのレイヤーキャッシュが使えないという制約がありました。この問題を解決するために、ECRキャッシュマニフェストを導入することにしました。

解決する課題

  1. CI環境でのDockerビルド時間の短縮
  2. 複数の開発者間やCI環境でのキャッシュ共有
  3. 古いキャッシュによるセキュリティリスクの軽減
  4. ストレージコストの最適化

実装方法

ECRキャッシュマニフェストは、BuildKitの機能を利用してリモートレジストリにビルドレイヤーをキャッシュする仕組みです。2023年10月からAWS ECRが正式にこの機能をサポートしました。

GitHub Actionsのワークフローファイルを修正し、BuildxでECRにキャッシュを保存・取得するよう設定します。また、古すぎるキャッシュによるセキュリティリスクを防ぐため、ECRのライフサイクルポリシーも設定します。

実装詳細

1. GitHub Actionsワークフローの設定

- uses: docker/setup-buildx-action@v3

- id: fullsha
  run: echo "sha_full=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT

- name: Build and Push ${{ matrix.component.name }} Image
  uses: docker/build-push-action@v5
  with:
    context: .
    file: ${{ matrix.component.dockerfile }}
    target: ${{ steps.env.outputs.environment }}
    push: true
    build-args: ${{ matrix.component.build_args }}
    tags: |
      ${{ env.ECR_REGISTRY }}/${{ env.REPO_PREFIX }}/${{ matrix.component.name }}:${{ steps.fullsha.outputs.sha_full }}
    cache-from: type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.REPO_PREFIX }}/${{ matrix.component.name }}:buildcache
    cache-to: type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.REPO_PREFIX }}/${{ matrix.component.name }}:buildcache,mode=max,image-manifest=true,oci-mediatypes=true

このワークフローの重要な点:

  • docker/setup-buildx-action@v3:BuildKitを有効化するステップ
  • cache-from:キャッシュの取得先を指定
  • cache-to:キャッシュの保存先を指定
  • mode=max:すべてのレイヤーをキャッシュ対象に
  • image-manifest=true,oci-mediatypes=true:ECRとの互換性確保のための設定

2. ECRライフサイクルポリシーの設定

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "buildcacheタグの有効期限を7日に設定",
      "selection": {
        "tagStatus": "tagged",
        "tagPrefixList": ["buildcache"],
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 7
      },
      "action": {
        "type": "expire"
      }
    },
    {
      "rulePriority": 2,
      "description": "タグ名に関わらず最新の15個のイメージを保持",
      "selection": {
        "tagStatus": "any",
        "countType": "imageCountMoreThan",
        "countNumber": 15
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}

このライフサイクルポリシーは:

  • buildcacheタグを7日で期限切れにする
  • タグに関わらず最新15個のイメージのみを保持し、それより古いイメージは削除する

おわりに

ECRキャッシュマニフェストの導入により、CIパイプラインの実行時間を大幅に短縮することができます。

ライフサイクルポリシーを適切に設定することで、コスト管理と古いキャッシュによるセキュリティリスクのバランスを取ることも重要です。

参考文献

タグ: #AWS #Docker #ECR #CI #GitHubActions #Performance #Caching