[アップデート]AWS CodeBuild のS3 キャッシュでキャッシュバージョン管理とプロジェクト間共有が可能になりました
お疲れさまです。とーちです。
AWS CodeBuild が S3 キャッシュ用のカスタムキャッシュキーをサポートするようになったというアップデートがありました。こちらのアップデートを実際に試してみたので、今回はその内容をお届けします。
CodeBuild のキャッシュ機能について
そもそも CodeBuild のキャッシュには「ローカルキャッシュ」と「S3 キャッシュ」の2種類があります。
ローカルキャッシュの特徴は、ビルドホストにキャッシュを持つことです。これによりネットワークを介さずにキャッシュにアクセスできますが、そのビルドホストのみが利用できるキャッシュという点に注意が必要です。
一方、S3 キャッシュの特徴としては、S3 バケットにキャッシュを保持することで複数のビルドホスト間でキャッシュを使い回せることが挙げられます。ローカルキャッシュと比べた場合のデメリットとしては、S3 からのダウンロード時間が追加でかかることです。このため依存ライブラリなどのキャッシュ対象の総容量が多い場合など、ビルド作業自体よりもキャッシュのダウンロードに時間がかかるときはローカルキャッシュのほうが良いでしょう。
今回のアップデートは S3 キャッシュに関するもので、S3 キャッシュ使用時にユーザーが任意のキャッシュキーを使用できるようになったというものです。これによってキャッシュのバージョン管理や、他の CodeBuild プロジェクト間でキャッシュを共有することが可能になりました。
それではさっそくやってみましょう。
やってみる
検証の前提条件
検証を始める前に、以下の条件を満たしていることを確認してください
- CodeConnection で GitHub と AWS アカウントを接続済であること
- CodeConnection による GitHub と AWS アカウントの接続手順は以下の公式ドキュメントをご確認ください
- https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html
- キャッシュ用の S3 バケットが作成済みであること
- 特別な設定などは必要なく普通に S3 バケットを作るだけなので作成方法は割愛します
キャッシュのバージョン管理を試す
今回は GitHub 上に buildspec.yml と package.json などのビルド時にインストールするパッケージ情報を書いたファイルを置いて、キャッシュの動作を確認してみます。
まずは CodeBuild プロジェクトを以下のように作成します。
キャッシュの設定は以下のような形です。
buildspec.yml は以下のように記載しました。
version: 0.2
phases:
build:
commands:
- echo "=== Starting build at $(date) ==="
- if [ -d "node_modules" ]; then echo "Cache HIT - node_modules exists"; else echo "Cache MISS - node_modules not found"; fi
- time npm install
- echo "=== Finished build at $(date) ==="
- du -sh node_modules
- find node_modules -type d -maxdepth 1 | wc -l
artifacts:
files:
- package.json
- package-lock.json
cache:
key: npm-$(codebuild-hash-files 'package-lock.json')
paths:
- 'node_modules/**/*'
keyの部分が新しく追加された設定ですね。文字通り、キャッシュキー名を指定する項目で、key名の一部として環境変数やコマンド置換が使えます。
私は知らなかったのですが、codebuild-hash-files
というCLIがCodeBuildの実行環境には備わっているようですね。 CodeBuild ソース ディレクトリ内のファイルの SHA-256 ハッシュを算出してくれるコマンドだそうです。
また package.json は以下のような状態です。
{
"dependencies": {
"aws-sdk": "^2.1692.0",
"next": "^15.2.4",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"typescript": "^5.8.2"
}
}
この状態で1回目のビルドをしてみます。
1回目のビルドの結果がこちらです。重要な部分以外は省略しています。
<省略>
[Container] 2025/03/31 02:55:27.023429 Parsing and expanding cache keys
[Container] 2025/03/31 02:55:27.032872 Expanded cache key: npm-$(codebuild-hash-files 'package-lock.json') -> npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 02:55:27.037806 Downloading S3 cache...
[Container] 2025/03/31 02:55:27.038546 Searching for cache with primary key: npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 02:55:27.107905 No cache found
[Container] 2025/03/31 02:55:27.108592 Unable to download cache: no caches were found with the provided cache keys
<省略>
[Container] 2025/03/31 02:55:27.851045 Running command echo "=== Starting build at $(date) ==="
=== Starting build at Mon Mar 31 02:55:27 AM UTC 2025 ===
[Container] 2025/03/31 02:55:27.862380 Running command if [ -d "node_modules" ]; then echo "Cache HIT - node_modules exists"; else echo "Cache MISS - node_modules not found"; fi
Cache MISS - node_modules not found
[Container] 2025/03/31 02:55:27.870519 Running command time npm install
npm warn deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
added 73 packages, and audited 74 packages in 20s
23 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
real 0m26.252s
user 0m10.841s
sys 0m2.363s
<省略>
[Container] 2025/03/31 02:55:54.139778 Running command du -sh node_modules
545M node_modules
[Container] 2025/03/31 02:55:54.178187 Running command find node_modules -type d -maxdepth 1 | wc -l
73
<省略>
[Container] 2025/03/31 02:55:54.232871 Uploading S3 cache...
[Container] 2025/03/31 02:55:54.272851 Saving cache at S3 path: ae802ee0-4271-4c3e-a8f0-7d3cc323bb7d/cfd480081b05b236f4092cac6130db6c/npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 02:55:58.691818 Cache saved with key: npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
<省略>
Expanded cache key: npm-$(codebuild-hash-files 'package-lock.json') -> npm-***
で 'package-lock.json' ファイルのハッシュ値が自動で展開されているのがわかります。
2025/03/31 02:55:27.107905 No cache found
となっており、初回のビルドなのでキャッシュがダウンロードできなかったことがわかりますね。
キャッシュ未使用時の npm インストールのコマンドの実行時間は、real 0m26.252s
なので、26.2 秒くらいです。
2025/03/31 02:55:54.272851 Saving cache at S3 path
となっているので S3 を見てみるとキャッシュが保存されていました。
ではこのまま、設定など何も変えずに2回目のビルドを行います。
2回目のビルドログがこちらです。
<省略>
[Container] 2025/03/31 03:01:46.944773 Expanded cache key: npm-$(codebuild-hash-files 'package-lock.json') -> npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 03:01:46.949326 Downloading S3 cache...
[Container] 2025/03/31 03:01:46.949924 Searching for cache with primary key: npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 03:01:47.106526 Cache hit for key: npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 03:01:47.106554 Downloaded cache archive from S3 path: ae802ee0-4271-4c3e-a8f0-7d3cc323bb7d/cfd480081b05b236f4092cac6130db6c/npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 03:01:47.142825 Download duration: 156ms
[Container] 2025/03/31 03:01:47.142856 Size: 114.83 MiB
[Container] 2025/03/31 03:01:47.142859 Unarchiving cache...
[Container] 2025/03/31 03:01:50.868145 Extraction duration: 3725ms
[Container] 2025/03/31 03:01:50.868164 Cache restored from key: npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
<省略>
[Container] 2025/03/31 03:01:51.594104 Running command echo "=== Starting build at $(date) ==="
=== Starting build at Mon Mar 31 03:01:51 AM UTC 2025 ===
[Container] 2025/03/31 03:01:51.605305 Running command if [ -d "node_modules" ]; then echo "Cache HIT - node_modules exists"; else echo "Cache MISS - node_modules not found"; fi
Cache HIT - node_modules exists
[Container] 2025/03/31 03:01:51.613064 Running command time npm install
up to date, audited 74 packages in 8s
23 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
real 0m13.649s
user 0m0.666s
sys 0m0.127s
<省略>
[Container] 2025/03/31 03:02:05.277224 Running command du -sh node_modules
545M node_modules
[Container] 2025/03/31 03:02:05.312842 Running command find node_modules -type d -maxdepth 1 | wc -l
73
<省略>
[Container] 2025/03/31 03:02:05.366449 Uploading S3 cache...
[Container] 2025/03/31 03:02:05.400002 Skipping cache generation, cache already exists for key: npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
[Container] 2025/03/31 03:02:05.400033 Found cache at S3 path ae802ee0-4271-4c3e-a8f0-7d3cc323bb7d/cfd480081b05b236f4092cac6130db6c/npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98 created at 2025-03-31 02:55:56 +0000 UTC
<省略>
Cache hit for key: npm-***
となっており、今回はキャッシュヒットできていますね。
Download duration: 156ms
などダウンロードやその展開にかかった時間もちゃんと表示してくれるんですね。あまりキャッシュ機能を使ったことがなかったので知りませんでした。これを見れば S3 キャッシュがいいかローカルキャッシュがいいかの判断の参考になりそうです。
npm インストールのコマンドの実行時間は、real 0m13.649s
13.6 秒くらいなので、当たり前ですが、キャッシュ未使用時の 26.2 秒と比べてビルド時間は短くなっています。
キャッシュのバージョン管理を試す(続き)
前置きが長くなりましたが、ここまでは従来も出来ていた普通の S3 キャッシュ機能になります。ここからは、キャッシュキーの値を変えることで新しくキャッシュし直す様子を確認してみましょう。
package.json の中身を変えてみましょう。変更した後は npm install
を行い、package-lock.json にも更新をかけます。その後、GitHub に push をします。
分かりづらいですが、 "aws-sdk": "^2.1690.0"
の部分が変わっています。
{
"dependencies": {
"aws-sdk": "^2.1690.0",
"next": "^15.2.4",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"typescript": "^5.8.2"
}
}
package-lock.json の中身が変わったことで、$(codebuild-hash-files 'package-lock.json')
で算出されるハッシュ値も変更されるはずです。
3回目のビルドログがこちらになります。
<省略>
[Container] 2025/03/31 03:22:55.968210 Expanded cache key: npm-$(codebuild-hash-files 'package-lock.json') -> npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:22:55.972806 Downloading S3 cache...
[Container] 2025/03/31 03:22:55.973328 Searching for cache with primary key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:22:56.048846 No cache found
[Container] 2025/03/31 03:22:56.049462 Unable to download cache: no caches were found with the provided cache keys
<省略>
[Container] 2025/03/31 03:22:56.731132 Running command echo "=== Starting build at $(date) ==="
=== Starting build at Mon Mar 31 03:22:56 AM UTC 2025 ===
[Container] 2025/03/31 03:22:56.741925 Running command if [ -d "node_modules" ]; then echo "Cache HIT - node_modules exists"; else echo "Cache MISS - node_modules not found"; fi
Cache MISS - node_modules not found
[Container] 2025/03/31 03:22:56.749235 Running command time npm install
npm warn deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
added 73 packages, and audited 74 packages in 19s
23 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
real 0m24.998s
user 0m10.722s
sys 0m2.210s
<省略>
[Container] 2025/03/31 03:23:21.770943 Running command du -sh node_modules
545M node_modules
[Container] 2025/03/31 03:23:21.808200 Running command find node_modules -type d -maxdepth 1 | wc -l
73
<省略>
[Container] 2025/03/31 03:23:21.864474 Uploading S3 cache...
[Container] 2025/03/31 03:23:21.901173 Saving cache at S3 path: ae802ee0-4271-4c3e-a8f0-7d3cc323bb7d/cfd480081b05b236f4092cac6130db6c/npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:23:26.117302 Cache saved with key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
<省略>
Searching for cache with primary key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
ということでちゃんとハッシュキーが変わっていますね。(以前のキーは:npm-70434d984db189e6aabde76c7010b35290736e190c35f41da6dacc9fea57ed98
)
それに伴い、No cache found
となりました。
Saving cache at S3 path:
ということで、ビルド完了後は再度キャッシュを S3 にアップロードしているのがわかります。
なお、キャッシュキーには npm-key-$CODEBUILD_RESOLVED_SOURCE_VERSION
のような形で環境変数をキーの一部とすることも可能になっていますので、ビルドの方法に合わせて、キャッシュキーをどのような名前にするか考えると良いのではないかと思います。
プロジェクト間のキャッシュ共有
プロジェクト間のキャッシュ共有も試してみます。
プロジェクト間でキャッシュを共有するには cacheNamespace
というパラメータを使います。
上記で作成した CodeBuild プロジェクトを編集して cacheNamespace
を追加します。
続いて、新しく CodeBuild プロジェクトを作成します。
新しい CodeBuild プロジェクトにも同じように cacheNamespace
を設定するのがポイントです。
この状態で初回のビルドを実施してみます。
<省略>
[Container] 2025/03/31 03:34:47.896807 Expanded cache key: npm-$(codebuild-hash-files 'package-lock.json') -> npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:34:47.901909 Downloading S3 cache...
[Container] 2025/03/31 03:34:48.154589 Searching for cache with primary key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:34:48.171282 No cache found
[Container] 2025/03/31 03:34:48.172063 Unable to download cache: no caches were found with the provided cache keys
<省略>
[Container] 2025/03/31 03:35:12.563185 Uploading S3 cache...
[Container] 2025/03/31 03:35:12.951529 Saving cache at S3 path: cachekey-update-shared/cfd480081b05b236f4092cac6130db6c/npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:35:17.392346 Cache saved with key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
<省略>
予想に反して、No cache found
となりましたね。これはなぜかというと、最初に作成した CodeBuild プロジェクトで、cacheNamespace
の変更をしたあとにビルドを行っていなかったからです。キャッシュ用の S3 バケットを見ると分かるのですが、
上記のように cacheNamespace
として設定した値でディレクトリが作成されています。cacheNamespace
を指定したビルドにより作成されたキャッシュは上記の通り、専用のディレクトリに配置されるようです。
上記のログを見ると分かるのですが、キャッシュのアップロード処理の部分が以下のようなログになっていることからも cachekey-update-shared ディレクトリにキャッシュが配置されたことがわかります。
Saving cache at S3 path: cachekey-update-shared/cfd480081b05b236f4092cac6130db6c/npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
気を取り直して3個目の CodeBuild プロジェクトを新規作成(設定は上記とほぼ同じなので割愛)し、キャッシュが使われるかを確認します。まっさらな状態でビルドを実行してみると以下のような結果になりました。
<省略>
[Container] 2025/03/31 03:41:43.717784 Expanded cache key: npm-$(codebuild-hash-files 'package-lock.json') -> npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:41:43.722630 Downloading S3 cache...
[Container] 2025/03/31 03:41:43.982403 Searching for cache with primary key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:41:44.109101 Cache hit for key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:41:44.109132 Downloaded cache archive from S3 path: cachekey-update-shared/cfd480081b05b236f4092cac6130db6c/npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:41:44.154727 Download duration: 126ms
[Container] 2025/03/31 03:41:44.154756 Size: 115.34 MiB
[Container] 2025/03/31 03:41:44.154760 Unarchiving cache...
[Container] 2025/03/31 03:41:46.955290 Extraction duration: 2800ms
[Container] 2025/03/31 03:41:46.955309 Cache restored from key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
<省略>
[Container] 2025/03/31 03:41:47.643789 Running command if [ -d "node_modules" ]; then echo "Cache HIT - node_modules exists"; else echo "Cache MISS - node_modules not found"; fi
Cache HIT - node_modules exists
[Container] 2025/03/31 03:41:47.651898 Running command time npm install
up to date, audited 74 packages in 9s
23 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
real 0m14.902s
user 0m0.706s
sys 0m0.110s
<省略>
[Container] 2025/03/31 03:42:02.570885 Running command du -sh node_modules
545M node_modules
[Container] 2025/03/31 03:42:02.644449 Running command find node_modules -type d -maxdepth 1 | wc -l
73
<省略>
[Container] 2025/03/31 03:42:02.768482 Uploading S3 cache...
[Container] 2025/03/31 03:42:03.003623 Skipping cache generation, cache already exists for key: npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39
[Container] 2025/03/31 03:42:03.003650 Found cache at S3 path cachekey-update-shared/cfd480081b05b236f4092cac6130db6c/npm-62f9774a5dd0c05d42ef53a82a4b317b84f72e2d7961d84ef79fc22260590d39 created at 2025-03-31 03:35:14 +0000 UTC
<省略>
はい、今度はちゃんとキャッシュが使われ、CodeBuild プロジェクト間でもキャッシュを共有できることが確認できました。
まとめ
AWS CodeBuild が S3 キャッシュ用のカスタムキャッシュキーをサポートするようになったというアップデートの紹介でした。
ユーザーが任意のキャッシュキーをつけられるようになったことで、よりキャッシュを管理しやすくなりましたね。またプロジェクト間でもキャッシュを使い回せるということで、同じようなライブラリを使用しているプロジェクトが複数あれば、恩恵を受けられそうなアップデートです。気になった方はぜひ試してみてください。
以上、とーちでした。