AWS CodeBuild、GitHub Actions、GitLab CI/CDにおけるキャッシュの書き方

記事タイトルとURLをコピーする

こんにちは。
アプリケーションサービス部、DevOps担当の兼安です。
今回は、AWS CodeBuild、GitHub Actions、GitLab CI/CDにおけるキャッシュの書き方についてまとめました。

はじめに - 本記事の対象者

本記事は、タイトルの通り、AWS CodeBuild(以降、CodeBuildと記述)、GitHub Actions、GitLab CI/CDにおけるキャッシュの書き方についてピンポイントで解説しています。
したがって、以下のような方を対象としています。

  • 既にAWS CodeBuild、GitHub Actions、GitLab CI/CDのいずれかの基礎知識があり、CI/CDパイプラインのチューニングを考えている方
  • asdfuvなどのバージョンマネージャーの基礎知識がある方
  • OSの基礎知識がある方

本記事で使用しているサンプルは、Pythonを用いたプロジェクトを用いています。
サンプルではPythonのインストールにasdf、依存関係の管理にuvを使用しています。
したがって、asdfuvの設定ファイルによって、プログラミング言語のバージョンと依存関係が決定されることをご理解ください。

asdfの設定ファイルは.tool-versionsであり、以下の設定となっています。

python 3.13.0

uvの設定ファイルは、pyproject.tomlであり、それをもとに生成されるuv.lockを使用しています。
pyproject.tomlの内容は以下の通りです。

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "cicd-pipeline-comparison"
version = "1.0.0"
description = "CI/CD pipeline comparison project using GitHub Actions, GitLab CI/CD, and AWS CodePipeline"
authors = [
    {name = "Developer", email = "developer@example.com"}
]
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "fastapi>=0.104.0",
    "uvicorn[standard]>=0.24.0",
    "pydantic>=2.5.0",
    "python-multipart>=0.0.6",
]

[tool.hatch.build.targets.wheel]
packages = ["modules"]

# 以下、省略します。  

この前提のもとで、キャッシュの書き方を解説していきます。

CI/CDにおけるキャッシュとは

まず、キャッシュとは、頻繁に使用されるデータを一時的に保存しておく仕組みのことです。
CI/CDにおけるキャッシュは、ビルドやテストの際に、依存関係のインストールやコンパイルなどの時間がかかる処理を高速化するために使用されます。
例えば、uvやasdfなどのバージョンマネージャーを使用している場合、依存関係のインストールに時間がかかることがあります。
このような場合、キャッシュを利用することで、次回以降のビルドやテストの際に、依存関係のインストールをスキップし、処理時間を短縮することができます。

一般的に、CI/CDツールの利用料金は、ビルドやテストの実行時間に基づいて計算されることが多いため、キャッシュを利用して処理時間を短縮することは、コスト削減にもつながります。
また、ビルドやテストの実行時間の短縮は、開発者の生産性向上や、ルール遵守の意識向上にも有効です。
実行時間が長すぎると、どうしてもCI/CDの実行を避けたくなり、自分の担当領域だけでテストするなどの行動を取りがちです。

AWS CodeBuildにおけるキャッシュの書き方

では、早速キャッシュの書き方を紹介します。
まずは、CodeBuildにおけるキャッシュの書き方です。

CodeBuildには、キャッシュを設定する方法が2つあります。

  • Amazon S3 にキャッシュ
  • CodeBuildがビルドする際に使用するホスト上にキャッシュ(ローカルキャッシュ)

それぞれ特徴があります。
この2つの違いについての詳細は、以下の記事をご覧ください。

blog.serverworks.co.jp

今回は2つの方法のうち、Amazon S3にキャッシュする方法で進めていきます。

CodeBuildでキャッシュを設定するには、ビルドプロジェクトの設定が必要です。
ビルドプロジェクトの設定画面で「追加設定」にある、「キャッシュタイプ」で、「Amazon S3」を選択します。
そして、「キャッシュバケット」にキャッシュを保存するS3バケットを指定します。
このとき、ビルドプロジェクトに紐づけているIAMロールに、「キャッシュバケット」で指定したAmazon S3バケットへのアクセス権限を付与するのを忘れないでください。

ビルドプロジェクトのキャッシュ設定

次に、buildspec.ymlファイルでキャッシュの設定を行います。
以下は、buildspec.ymlファイルの例です。

version: 0.2

phases:
  # 途中省略します。  

cache:
  key: cache-key-$(codebuild-hash-files .tool-versions)-$$(codebuild-hash-files uv.lock)
  paths:
    - '/root/.cache/pip/**/*'
    - '/root/.cache/uv/**/*'
    - '/root/.cargo/**/*'
    - '/root/.asdf/**/*'
    - '/root/.local/bin/**/*'

codebuild-hash-files関数は、CodeBuildが提供する関数で、指定したファイルの内容に基づいてハッシュ値を生成します。
このハッシュ値をキャッシュキーに含めることで、.tool-versionsuv.lockに変更がなければ、同じキャッシュが再利用されます。
これらに変更があった場合、新しいキャッシュが作成されるという動きをします。

pathsセクションでは、キャッシュするディレクトリを指定します。
ここでは、pipuvcargoasdfのキャッシュディレクトリを指定しています。
これにより、これらのディレクトリがキャッシュされ、次回以降のビルドで再利用されます。

パスの指定にはワイルドカードが必要であることに注意してください。
例えば、/root/.cache/pipと指定すると、pipディレクトリ自体はキャッシュされますが、その中のファイルやサブディレクトリはキャッシュされません。
つまり、パスそのものではなく、パスパターンに合致するものがキャッシュ対象です。

GitHub Actionsにおけるキャッシュの書き方

次に、GitHub Actionsにおけるキャッシュの書き方を紹介します。

jobs:
  # キャッシュ作成ジョブ
  prepare:
    name: Prepare
    runs-on: ubuntu-latest
    environment: production
    outputs:
      cache-key: ${{ steps.cache-key.outputs.key }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v5

      - name: Generate cache key
        id: cache-key
        run: |
          CACHE_KEY="cache-$(sha256sum .tool-versions uv.lock | sha256sum | cut -d' ' -f1)"
          echo "key=$CACHE_KEY" >> $GITHUB_OUTPUT
          echo "Cache key: $CACHE_KEY"

      - name: Cache dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.asdf
            ~/.cache/pip
            ~/.cache/uv
            ~/.cargo
            ~/.local/bin
          key: ${{ steps.cache-key.outputs.key }}

      # この後に、各種インストールが続きます。  

GitHub Actionsでキャッシュを設定するには、actions/cacheアクション(そういう出来合いの部品が提供されていると思ってください)を使用します。
この例では、キャッシュキーを生成するステップと、キャッシュを保存するステップを分けています。
steps.cache-key.outputs.keyは、前のステップで生成されたキャッシュキーを参照する記述です。

キャッシュキーの作り方自体は、CodeBuildと似ています。
ファイルをハッシュ化するコマンドsha256sumを使用して、.tool-versionsuv.lockの内容に基づいてキャッシュキーを生成しています。
少し工夫して、2つのファイルのハッシュ値を連結したものをさらにハッシュ化し、最後にcutコマンドで余分な部分を削ったものをキャッシュキーとしています。
ここまでやる必要はないかもしれませんが、キャッシュキーが長くなりすぎるのを防ぐためにこのようにしています。

そして、CodeBuildと同様に、pathセクションでキャッシュするディレクトリを指定しています。
CodeBuildと同様に、パスを列挙していますが、GitHub Actionsの場合は、指定したパスが丸ごとキャッシュされるので、ワイルドカードは不要です。
個人的にはこちらの方が直感的に感じます。

GitLab CI/CDにおけるキャッシュの書き方

最後に、GitLab CI/CDにおけるキャッシュの書き方を紹介します。

# キャッシュ作成ジョブ
prepare:
  stage: prepare
  image: ubuntu:latest
  before_script:
    # ここに各種インストールのコマンドを記述します。  
  script:
    - echo "Preparation complete."
  cache:
    - key:
        files:
          - .tool-versions
          - uv.lock
      paths:
        - .cache/pip
        - .cache/uv
        - .cargo
        - .asdf

書き方はGitHub Actionsに似ています。
パスの指定も同様に、ワイルドカードは不要です。
キャッシュキーにファイルを使用できる点は他のツールと同じですが、ハッシュ関数を使うのではなく、filesセクションにキャッシュキーの元となるファイルを列挙する形になります。

キャッシュの設定にはOSの知識がある方が有利

以上が、CodeBuild、GitHub Actions、GitLab CI/CDにおけるキャッシュの書き方の紹介でした。
なお、各ツールのキャッシュ設定ですが、ツール間の移植性はあまり高くありません。
理由はいくつかあります。

今回、3つのツールで、ビルド環境としてubuntu:latestのコンテナイメージを使用していますが、同じコンテナイメージでもツールごとでプリインストールされているソフトウェアのバージョンが異なる場合があります。

また、同じコンテナイメージでもビルドを行うときの実行ユーザーやホームディレクトリの場所も異なる場合があります。
GitHub ActionsとGitLab CI/CDでキャッシュパスの指定に差があるのはこれが理由です。
このあたりは、使用するツールやビルド環境によって多岐にわたるため、詳細は割愛させていただきます。

それぞれのツールで実際に動かしてみて、Linuxベースのイメージなら、ビルドコマンドの途中に以下のコマンドを入れて、その結果を確認してみると良いと思います。

  • カレントユーザーを調べる: whoami
  • カレントディレクトリを調べる: pwd
  • ホームディレクトリを調べる: echo $HOME
  • ディレクトリツリーを調べる: tree(インストールが必要な場合があります)

参考

兼安 聡(執筆記事の一覧)

アプリケーションサービス部 DS3課所属
2025 Japan AWS Top Engineers (AI/ML Data Engineer)
2025 Japan AWS All Certifications Engineers
2025 AWS Community Builders
Certified ScrumMaster
PMP
広島在住です。今日も明日も修行中です。