Cloud Build で Docker イメージをビルド

Google Cloud Buildは、CI/CD をホストするサービスです。
Artifact Registryと統合されており、GKE で動作させる docker イメージをビルドする用途に適しています。また、ほかにも Java ビルドなどにも対応しています。

Cloud Build は日ごとの無料枠を提供しているため、実験的な小規模ビルドであれば無料枠におさまるでしょう。 コスト面では長期運用した際に Artifact Registry 側でかかるストレージコストを多少意識した方が良いでしょう。
実運用の際には旧世代のイメージを削除する操作がおそらく必要です。

また、docker buildコマンドをホストしているため、ビルド過程の大半は docker のビルドプロセスと同じです。

用意するもの

  1. gcloud コマンド(Google Cloud SDK) & GCP アカウント
  2. docker イメージビルド用リソース(Dockerfile など、docker build と同じもの)
  3. YAML 形式のビルド設定ファイル

既存の docker ビルドリソースを移行する場合、YAML 設定ファイルを追加作成するだけで利用開始できるケースも多くありそうです。

ビルド設定ファイル

docker イメージをビルドするためのビルドステップの定義は、以下のような形式になります。

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'pkg.dev/project-name/repo-name/image-name', '.']
images: ['pkg.dev/project-name/repo-name/image-name']

steps.nameは Container Builder が実行するイメージです。docker のビルドには gcr.io/cloud-builders/docker を用います。
steps.argsは、コマンドライン引数です。gcr.io/cloud-builders/docker イメージが docker コマンドを提供しているため、この例の組み合わせでは

docker build -t pkg.dev/project-name/repo-name/image-name .

が Cloud Build 上で実行されます。

Dockerfile など.が指すリソースは、後述のgcloud buildsコマンドで転送します。

imagesは Artifact Registry にプッシュするイメージを指定します。この項に設定したイメージは GKE で実行可能です。また、asia-docker.pkg.dev などの pkg.dev ファミリーも指定可能です。

キャッシュを利用する

Cloud Build はデフォルト指定では Docker イメージビルドにキャッシュを利用せず、毎回すべてのレイヤを新規ビルドします。
キャッシュを利用するためには、--cache-fromオプションを args に追加します。
詳細な書式は、公式ドキュメントの ビルドを高速化する際のおすすめの方法を参照してください。

キャッシュで注意すべき点として、初回ビルド時には Container Registry にキャッシュが存在していないためエラーになることです。少なくとも一度は--cache-fromオプションを指定せずにビルドしておく必要があります。

gcloud builds コマンド

ビルド実行は、

$ gcloud builds submit ./ --config build-step.yaml [--region=asia-northeast1]

のように gcloud コマンドで指定すると即開始します。

config オプションには先ほど作成した yaml ファイルを指定します。
また、Dockerfile などビルドに必要なリソースは、引数としてディレクトリを指定します。この例では、./のとおりカレントディレクトリに存在しているファイル一式を圧縮・転送します。

--regionはオプショナルではありますが、省略するとデフォルトの米国リージョン(--global)を選択します。たとえば Artifact Registry が asia の構成では大陸間ネットワーク転送料がかかるようです。
コンテナイメージのサイズを意識しづらい点と合わせて、由来の分かりにくいコスト要因といえます。

Dockerfile のCOPYディレクティブなども、gcloudで転送したリソースを利用可能です。
転送除外したいファイルは .gcloudignoreファイルで指定できますが、転送したいリソースだけを単にサブディレクトリに整理しておく手もあります。

その他のオプションは 公式リファレンスを参照してください。

ビルド用サービスアカウントの必要権限

サービスアカウント向けの権限は人が操作する際に必要な権限と異なります。

CloudBuild を自動化する際のサービスアカウントは、「Cloud Build サービスエージェント・ Service Usage ユーザー・ログ書き込み」の 3 種のロールを指定すると動作します。

公式ドキュメントの説明とは異なる点と、目的別のロールになっていない点には注意が必要です。
またロギングについては ビルドログの保存と管理に解説がありますが、サービスアカウントはデフォルトのログ出力先に書けない挙動となっているため、多くのシナリオでは追加の設定が必要でしょう。

比較的簡素な方法は、Cloud Logging のみにログ出力する構成です(ビルド時オプション)。

GCP の IAM は一見無関係なエラーに見え、ドキュメントの記述が正確でなく、和訳がサービス表記と異なるため迷宮入りしがちです。
gcloud builds submit --verbose=debugオプションを指定すると具体的なエラー内容が出力されます。

ArtifactRegistry へのアクセス権

CloudBuild は同一プロジェクトの ArtifactRegistry へのアクセス権は設定済みです。
他プロジェクトのレジストリにアクセスしたい場合には、そのプロジェクトの IAM に「ArtifactRegistry 読み取り」などの適切な権限を追加する必要があります。

サービスアカウントの ID は、 Google Cloud サービスのデフォルトの権限にリストされているもののうち、PROJECT-NUMBER@cloudbuild.gserviceaccount.comです。

PROJECT-NUMBER は普段使う機会がないため分かりづらいのですが、プロジェクト ID ではなくクラウドコンソールのダッシュボードに記載されている数値です。
ArtifactRegistry にアクセスするのは、CloudBuild を呼び出したユーザーのアカウントでもないことに注意が必要です。

Docker Hub のミラー

Google Artifact Registry は Docker Hub の公式リポジトリをミラーしています。Cloud Build から見てネットワークが近いというキャッシュのメリットのほか、長い目でみると Docker Hub の継続性への疑問をヘッジする面でも有効と考えられます。

主要な公式イメージは、Docker Hub の library に集められているため、以下のコマンドを実行することにより、mirror.gcr.io 上のイメージ識別子を取得できます。

$ gcloud container images list --repository=mirror.gcr.io/library
⁋ 2018/05/09↻ 2026/03/12
中馬崇尋
Chuma Takahiro