🐳

CodeBuildでdocker buildを高速化できるポテンシャルを持つネタ 3選

2024/07/04に公開

概要

CodeBuildを使ってコンテナイメージをビルドしてECSやApp RunnerなどのコンテナサービスにデプロイをするCI/CDパイプラインを作る際、コンテナイメージのビルド時間を短くしたい!

CIは早いに越したことはない!ので、そのような期待は皆さんお持ちなのではないでしょうか?

そんなときにコンテナイメージをビルドするのにかかる時間(CodeBuildの実行時間)をなるべく短くする方法で効果を発揮しそうな3ネタを紹介します。

本記事では、以下の3ネタを紹介します。

  • CodeBuildのインスタンスサイズを適切なものを選ぶ
  • CodeBuildのローカルキャッシュを有効化する
  • docker buildコマンドでremote cacheを使う

1つずつ見ていきたいと思います。

CodeBuildのインスタンスタイプを適切なものを選ぶ

コンテナイメージのビルドはビルド環境のマシンスペックに依存します。
LINUX_CONTAINERで見ても、Small, Medium, Large, XLarge, 2XLargeと5種類あるためハイスペックなインスタンスタイプを選ぶことでビルド時間を短縮することができるはずです。

しかし、インスタンスタイプをハイスペックなものにすることは当然コストのかかることです。2倍のスペックにしてビルド時間が1/2以下になるのであれば迷わず採用すればいいと思いますが、そこまで劇的にビルド時間を短縮できないのであればコストとの兼ね合いでインスタンスタイプを選ぶことになるでしょう。各スペックでベンチマークを取りコストとパフォーマンスで組織に最適なインスタンスタイプを選ぶことが重要になってきます。

インスタンスタイプ一覧はこちらを参照ください。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-env-ref-compute-types.html

CodeBuildのローカルキャッシュを有効化する

AWS CodeBuild でキャッシュを利用することができ、利用できるキャッシュのうち、ローカルキャッシュというものを利用することでビルド時間を短縮することができる場合があります。

ローカルキャッシュのドキュメント:
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-caching.html#caching-local

キャッシュモードには以下の3種類があります。

  • ソースキャッシュモード
    • Gitメタデータをキャッシュする
    • 大きな Git リポジトリであるソースを持つプロジェクトに適している
  • Docker レイヤーキャッシュモード
    • 既存の Docker レイヤーをキャッシュする
    • 大きな Docker イメージを構築または取得するプロジェクトに適している
    • 大きな Docker イメージをネットワークからプルすることによって生じる負荷問題を回避できる
  • カスタムキャッシュモード
    • 上記2つのパターン以外の時に使う

注意事項としては、

そのビルドホストのみが利用できるキャッシュをそのビルドホストにローカルに保存します。キャッシュはビルドホストですぐに利用できるため、この方法は大規模から中間ビルドアーティファクトに適しています。ビルドの頻度が低い場合、これは最適なオプションではありません。

とあるようにCodeBuildのコンテナを使い回す場合に効果を発揮しますが、CodeBuildのコンテナがクリーンアップされる場合はキャッシュが利用できないです。
ビルド頻度が高い、もしくは連続してビルドする際に高速化されることに期待する場合は効果を発揮するでしょう。

docker buildコマンドでremote cacheを使う

こちらにあるようにremote cacheを使う方法になります。仕組みとしては、ECRなどのコンテナレジストリにコンテナイメージとキャッシュ用のイメージを2つ保存しておき、キャッシュ用イメージを使い、ビルドする形になります。
https://www.docker.com/ja-jp/blog/image-rebase-and-improved-remote-cache-support-in-new-buildkit/

少し長くて見にくいですが、以下のようなコマンドになります。

  • --cache-from: キャッシュとして使うイメージ
  • --cache-to: キャッシュ先(今回ビルドするものを新しいキャッシュとして保存)
docker buildx build -t $repo_name:$image_tag --cache-to mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=$account_id.dkr.ecr.$AWS_DEFAULT_REGION.amazonaw
s.com/repo:cache-image --cache-from type=registry,ref=$account_id.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/repo:cache-image --load .

キャッシュを使う、キャッシュを更新する、というサイクルを繰り返しながらビルドするため、大きな変更がない場合やレイヤーなどの管理がうまくできていてキャッシュが効果的に利用できるイメージの場合は大きな効果がある方法となります。

注意点としてはbuildxを使うためにセットアップが必要になることがあるくらいかと思います。
この方法はコストをあまりかけることなく実現できるため動作環境を選ばず使えることはメリットと言えるかもしれません。

まとめ

いかがでしたでしょうか、コンテナイメージのビルドを高速化するネタ紹介でした。
それぞれのネタがどのくらい高速化に寄与するかは、CIの実行頻度や前回のビルドとの差分に依存することので有効化どうかは各環境によって差があることやCodeBuildのインスタンスタイプを高スペックにすると利用料金も上がることから高速化するために払うべきコストなのかという判断も必要かと思います。
とはいえ、CI/CDパイプラインというものを1度作って安定してデプロイができていると、CIやCDにかかる時間についてある程度時間がかかっていても、「まあ、それくらいかかって普通だよね」という感覚になることもあるかと思います。
ソースコードを継続的にリファクタリングして改善していくのと同じように、CI/CDパイプラインにも改善の余地がないかを考え、継続的に改善をしていけると良いなと思い、そのきっかけやその時の改善策の1つとして役立てば幸いです。

Discussion