Cloud Buildは、Google Cloud上でビルド・テスト・デプロイを実行するフルマネージドのCI/CDサービスです。ビルド用のサーバーを持たずに、リポジトリへのpushをきっかけにコンテナイメージを作り、Cloud RunやGKEへデプロイするところまで自動化できます。前提はこの2年で何度も変わりました。2024年にデフォルトのサービスアカウントが変わり、2025年3月にContainer Registryが止まり、2025年11月に料金がリージョン別になりました。さらに2027年3月28日には、ビルドを動かすワーカーの既定がDocker Engine 20.10からDocker Engine 29へ切り替わります。この記事では、料金(東京リージョンの単価を含む)、最初のビルドを通す手順、cloudbuild.yamlの書き方、トリガーとAPIでの起動、権限の落とし穴を、2026年10月時点の公式ドキュメントと手元での実測に沿って整理します。
まとめ
無料枠は請求先アカウントごとに月2,500ビルド分(デフォルトプールのe2-standard-2)で、小規模なチームなら無料枠の中で回せます。e2-standard-2は東京リージョンでもus-central1と同じ$0.006/分ですが、e2-highcpu-8とe2-highcpu-32は東京のほうが28%高くなります。ビルド定義はcloudbuild.yamlにstepsを並べるだけで、1ステップが1コンテナとして順に実行されます。
権限エラーが出たら、まずビルドを実行したサービスアカウントを確かめてください。どのサービスアカウントが使われるかは、そのプロジェクトで初めてビルドを実行した時期と組織ポリシーで変わります。ユーザー指定のサービスアカウントに切り替えると、ログの出力先も指定しなければなりません。もう1つは2027年3月28日のワーカー切替です。Docker 29のワーカーがBuildKitで動く場合、キャッシュ元のイメージにBuildKit用のメタデータが無いと、--cache-fromはエラーを出さずにキャッシュを使いません。BUILDKIT_INLINE_CACHE=1を付けておけば、切替後の最初のビルドでメタデータ付きのイメージがpushされ、2回目からキャッシュが効きます。
Cloud Buildの実行モデル|1ステップ=1コンテナ
Cloud Buildは、指定したコンテナイメージを順番に実行する仕組みです。1つのビルドは複数のステップから成り、各ステップには「どのイメージで」「どのコマンドを」実行するかを書くだけです。ステップ同士は/workspaceディレクトリを共有するので、前のステップが作ったファイルを次のステップがそのまま使えます。
ビルド環境はnameに書いたDockerイメージそのものなので、ビルドサーバーの保守やエージェントの更新は要りません。上限は1ビルドあたり300ステップ、1ステップの引数100個、1引数10,000文字です(Cloud Buildの割り当てと上限)。
典型的な使い方は、GitHubへのpushをトリガーにDockerイメージをビルドし、Artifact Registryに格納し、Cloud RunやGKEへデプロイする流れです。テスト、Terraformの適用、静的解析も同じstepsに並べられます。承認ゲートやカナリアリリースまで要るなら、デプロイ部分はCloud Deployに渡す構成も選べます。
Cloud Buildの料金|東京リージョンの単価と無料枠
無料枠は月2,500ビルド分
課金単位はビルド分(build-minute)で、1分未満は秒単位です。請求先アカウントごとに月2,500ビルド分が無料で、対象はデフォルトプールのe2-standard-2です。キューで待っている時間は課金されず、1ビルド3分なら月833回まで無料枠に収まります。公式の料金ページはこの無料枠を「プロモーション枠で、上限は変更されうる」と注記しているので、恒久的な保証ではありません。
マシンタイプ別の分単価(us-central1と東京)
2025年11月1日にe2マシンタイプの新料金が適用され、全リージョン一律だった単価がリージョンごとに変わりました。デフォルトプールの単価は次のとおりです(Cloud Build pricing update)。
| マシンタイプ | vCPU / メモリ | us-central1 | 東京(asia-northeast1) | 無料枠 |
|---|---|---|---|---|
| e2-medium | 1 / 4GB | $0.003/分 | $0.00384/分 | 対象外 |
| e2-standard-2(既定) | 2 / 8GB | $0.006/分 | $0.006/分 | 月2,500分 |
| e2-highcpu-8 | 8 / 8GB | $0.0156/分 | $0.019968/分 | 対象外 |
| e2-highcpu-32 | 32 / 32GB | $0.0624/分 | $0.079872/分 | 対象外 |
既定のe2-standard-2だけは東京でも単価が変わりません。e2-mediumとe2-highcpu系は東京のほうが28%高く、e2-highcpu-8で1回5分のビルドを月200回回すと、東京で約$20、us-central1で約$15.6です。ソースや成果物を東京に置く必要がなく、上位マシンを多用するなら、ビルドだけus-central1で動かすのも選択肢になります。n1-highcpu-8とn1-highcpu-32も指定できますが非推奨で、価格はe2-highcpu系と同じです。
マシンタイプを上げるべきかの判断
変更はgcloud builds submit --machine-typeか、cloudbuild.yamlのoptions.machineTypeで行います。請求額は所要時間×単価なので、8vCPUで所要時間が4分の1になるなら、単価が2.6倍でも合計は安くなります。並列テストやマルチステージビルドのように並列度を上げられる処理ほど、上位マシンが有利です。単一スレッドのコンパイルやネットワーク待ちが支配的なビルドでは、vCPUを増やしても時間は縮まず請求だけが増えます。まず既定のe2-standard-2で計測し、CPUが詰まっていると分かってから上げてください。
同時実行の上限にも注意が要ります。デフォルトプールの同時ビルド数は既定で10〜30(globalリージョンでの値)、同時に使えるE2のvCPUはリージョンごとに既定で5〜100で、どちらも引き上げ申請ができません。vCPUの枠が100なら、e2-highcpu-32のビルドは同時に3本までしか走りません。これ以上を求めるならプライベートプールに移ります。
最初のビルドを通すまでの手順
APIの有効化とレジストリの準備
Google Cloudのプロジェクトを用意したら、Cloud Build APIを有効化し、イメージの置き場所になるArtifact Registryのリポジトリを作ります。ここを飛ばすと最初のpushで失敗します。
gcloud config set project YOUR_PROJECT_ID
gcloud services enable cloudbuild.googleapis.com artifactregistry.googleapis.com run.googleapis.com
gcloud artifacts repositories create my-repo \
--repository-format=docker --location=asia-northeast1
APIを有効化すると、ビルドを実行するサービスアカウントが用意されます。どのサービスアカウントになるかは初回ビルドの実行時期と組織ポリシーで変わり、これが後述の権限の落とし穴につながります。
ローカルのソースからのビルド実行
トリガーやリポジトリ連携を設定する前に、手元のソースを直接投げて動作を確かめるのが早道です。カレントディレクトリの内容がアップロードされ、Cloud Build上でビルドが走ります。
gcloud builds submit --region=asia-northeast1 \
--tag asia-northeast1-docker.pkg.dev/YOUR_PROJECT_ID/my-repo/my-app:v1 .
この1行で、Dockerfileを使ったイメージのビルドとArtifact Registryへのpushまで終わります。cloudbuild.yamlを使う場合は--configで指定し、--tagは外します。Dockerfileの書き方に不安があるなら、Dockerfileの主要命令とベストプラクティスを先に押さえておくと、ビルド時間の短縮にも効きます。
cloudbuild.yamlの書き方
stepsの基本構文
ビルド定義はYAML(cloudbuild.yaml)かJSON(cloudbuild.json)で書きます。機能差はないので、人が保守するならコメントを書けるYAML、ツールで自動生成するならJSONを選びます。テスト、イメージのビルド、Cloud Runへのデプロイまでをつないだ最小構成は次のとおりです。リポジトリのルートにnpm testを定義したpackage.jsonとDockerfileがあり、上の手順でCloud Run APIも有効化してある前提です。
steps:
- name: 'node:22'
entrypoint: 'npm'
args: ['ci']
- name: 'node:22'
entrypoint: 'npm'
args: ['test']
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA']
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: 'gcloud'
args: ['run', 'deploy', 'my-app',
'--image', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA',
'--region', 'asia-northeast1']
timeout: '1200s'
nameは実行するビルダーイメージ、argsはそこへ渡す引数、entrypointはイメージ既定のエントリポイントを上書きするときに書きます。dirを書くと作業ディレクトリが/workspace/<dir>になり、モノレポで特定のサブディレクトリだけビルドするときに使えます。argsの代わりにscriptでシェルスクリプトを直接書くこともできますが、argsやentrypointとは併用できません。
手動ビルドでの置換変数の指定
$PROJECT_IDや$SHORT_SHAは組み込みの置換変数ですが、COMMIT_SHA・SHORT_SHA・BRANCH_NAMEなどはGitのイベントから値が渡るため、トリガー経由のビルドでしか設定されません。gcloud builds submitではエラーにならず空文字に置き換わり、上のyamlをそのまま手動実行するとmy-app:という不正なイメージ名になってpushで落ちます。手動実行では値を明示的に渡してください。どのビルドでも必ず使えるのは$PROJECT_ID・$PROJECT_NUMBER・$BUILD_ID・$LOCATIONの4つだけです。
gcloud builds submit --region=asia-northeast1 --config cloudbuild.yaml \
--substitutions SHORT_SHA=$(git rev-parse --short HEAD)
timeoutとimagesの挙動
timeoutを省略した場合の既定値は60分、最大は24時間です(ビルド構成ファイルのスキーマ)。ビルドが1時間で止まったら、ビルドの状態がTIMEOUTになっているかと、構成のtimeoutの値を確かめます。
imagesに書いたイメージは、全ステップが成功した後にCloud Buildが自動でpushします。途中のステップが落ちればpushされないので、失敗したビルドのイメージがレジストリに残りません。ただし上の例のように同じビルドの中でデプロイまで行う場合、デプロイのステップが動く時点では自動pushがまだ走っていません。イメージが見つからずに失敗するため、デプロイの前に明示的なdocker pushのステップを挟みます。push先はArtifact Registryです。gcr.io/cloud-builders/dockerのようなGoogle提供のビルダーイメージは、Container Registryの停止後もそのまま使えます。
Secret ManagerによるAPIキー・トークンの受け渡し
プライベートレジストリのトークンや外部APIキーをenvに平文で書くと値がcloudbuild.yamlに残り、ステップのコマンドが値を出力すればビルドログにも残ります。Secret Managerのシークレットを環境変数として渡してください。
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_NUMBER/secrets/npm-token/versions/latest
env: 'NPM_TOKEN'
steps:
- name: 'node:22'
entrypoint: 'bash'
args: ['-c', 'npm config set //registry.npmjs.org/:_authToken=$$NPM_TOKEN && npm ci']
secretEnv: ['NPM_TOKEN']
シークレットの参照は置換変数と区別するためドル記号を2つ重ねます($$NPM_TOKEN)。ビルドを実行するサービスアカウントにはroles/secretmanager.secretAccessorが要ります。
ビルドを速くする|キャッシュの効かせ方
Cloud Buildのビルドは毎回まっさらなVMで始まるので、何もしなければDockerのレイヤキャッシュは効きません。依存のインストールのように変更の少ない層に時間がかかっているビルドなら、マシンタイプを上げる前にキャッシュを効かせるほうが安く済みます。定番は、前回のイメージをpullして--cache-fromに渡す方法です。
steps:
- name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args: ['-c', 'docker pull asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:latest || exit 0']
- name: 'gcr.io/cloud-builders/docker'
args: ['build',
'-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:latest',
'--cache-from', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:latest',
'--build-arg', 'BUILDKIT_INLINE_CACHE=1',
'.']
images: ['asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:latest']
1つ目のステップで前回のイメージを取得し(初回は存在しないのでexit 0で握りつぶします)、2つ目でそれをキャッシュ元に指定します。末尾のimagesが無いと:latestが一度もpushされず、次回以降のpullが空振りし続けます。Dockerfile側で依存ファイルのCOPYとソースのCOPYを分けておくと、ソースだけを変えたときも依存のインストール層のキャッシュが残ります。
--build-arg BUILDKIT_INLINE_CACHE=1は、2027年3月28日のワーカー切替後にビルドがBuildKitで動いた場合に備えた1行です。公式のビルド高速化のページ(2026年10月22日更新)の例にはこの指定がありません。さらに、同じページのYAML例は--cache-fromの値の後ろのカンマが抜けていて、PyYAMLで読み込むと構文エラーになります。理由は後述の「2027年3月28日のワーカー切替」で説明します。
2026年のCloud Buildの変更点
Cloud Buildのリリースノートに載った2026年の変更のうち、構成や運用に影響するものを並べます。
| 日付 | 変更 |
|---|---|
| 2026-02-12 | asia-southeast3(バンコク)で提供開始 |
| 2026-03-16 | OCIイメージをArtifact Registryへアップロード |
| 2026-03-30 | 汎用アーティファクトのアップロードと依存取得 |
| 2026-05-15 | resultsフィールド(ステップのデータをアテステーションへ添付) |
| 2026-06-24 | GitLab Enterprise等の接続で呼び出し元の権限も確認 |
| 2026-08-24 | CVE-2026-19410を修正(対応不要) |
| 2026-08-28 | 第2世代GitLab・Bitbucket接続のトークンを画面で更新 |
| 2026-10-12 | ワーカーのリリースチャネルを選択可能に |
6月24日以降、GitLab EnterpriseとBitbucket Data Centerの接続を作る操作者本人にも、参照先シークレットのsecretmanager.versions.access権限が要ります。既存の利用者に最も影響するのは、10月12日のリリースチャネルです。
2027年3月28日のワーカー切替|Docker 20.10からDocker 29へ
リリースチャネルとワーカーの版
Cloud Buildのビルドは、Googleが管理するVM(ワーカー)上のDockerで動きます。2026年10月12日から、このワーカーのOSとDockerの更新頻度をリリースチャネルで選べるようになりました。2027年3月28日までは既定がlegacyで、それ以降はregularが既定になります。
| 版・チャネル | Docker / OS | 更新頻度・サポート期限 |
|---|---|---|
| legacy(2027-03-27まで既定) | Docker Engine 20.10 / Debian 11 | 2028-03-31まで |
| 2026.09(regular・rapid・stable) | Docker Engine 29 / Debian 13 | 2029-09-30まで |
| regular(2027-03-28から既定) | 新版の公開から4週間以内に追従 | – |
| rapid | 常に最新版 | – |
| stable | 年1回(通常2月) | – |
チャネルが決めるのはワーカーのDockerとOSだけで、各ステップのコンテナの中身は変わりません。それでも、ステップからDockerを操作する処理には次の2つの差が出ます。
BuildKitでのキャッシュ元イメージの条件
Cloud Buildの定番ビルダーgcr.io/cloud-builders/docker:latestに入っているDocker CLIは20.10.24でした。このCLIは、どのビルダーを使うかを接続先のデーモンに合わせて決めます。2026年10月26日に、Mac上のcolima(Docker 29.5.2)で動かしたdindを相手に、このイメージからdocker:20.10-dind(Docker Engine 20.10.24)とdocker:29-dind(同29.9.2・設定は既定のまま)へ接続し、同じ手順を流しました。手順は、ビルドしてレジストリへpushし、ローカルのイメージとビルドキャッシュを消してから(新しいVMを模すため)、pullして--cache-from付きで再ビルドする、というものです。依存のインストールの代わりにsleep 5を入れた検証用のDockerfileを使ったので、表の秒数はキャッシュが使われたかどうかの目印で、Cloud Build上の所要時間ではありません。
| デーモン | 使われたビルダー | BUILDKIT_INLINE_CACHE=1 | 依存層のRUN | 再ビルド時間 |
|---|---|---|---|---|
| Docker Engine 20.10.24 | 従来ビルダー | なし | Using cache | 4秒 |
| Docker Engine 20.10.24 | 従来ビルダー | あり | Using cache(警告のみ) | 5秒 |
| Docker Engine 29.9.2 | BuildKit | なし | 再実行(5.3秒) | 8秒 |
| Docker Engine 29.9.2 | BuildKit | あり | CACHED | 3秒 |
Docker 29ではCLIを変えていないのにBuildKitで動きました。BuildKitは、キャッシュ用のメタデータが埋め込まれていないイメージを--cache-fromに指定してもキャッシュとして使いません(Dockerのinline cacheの説明)。エラーは出ずに全層を作り直すので、遅くなって請求が増えるだけで気づきにくい失敗です。BUILDKIT_INLINE_CACHE=1は従来ビルダーでは警告が出るだけで、キャッシュはそのまま効きました。ただし従来ビルダーが作ったイメージにはBuildKit用のメタデータが入らないため、切替後の最初の1回はキャッシュが外れ、そのビルドでpushしたイメージから効き始めます。BuildKitの仕組みとキャッシュの種類はBuildKitの解説記事にまとめています。
Cloud Buildの新ワーカーがBuildKitを既定にするかどうかは、2026年10月時点の公式ドキュメントに書かれていません。Docker Engine 23.0以降の既定はBuildKitなので、そうなる前提で備えておくのが安全です。regularで一度ビルドし、ログの先頭がStep 1/3形式(従来ビルダー)か#1 [internal] load build definition形式(BuildKit)かを見れば判別できます。
ステップのDocker CLIとAPIバージョンの互換性
ステップの中でDocker CLIを使う場合、CLIのAPIバージョンが古すぎるとデーモンに拒否されます。Docker 29.5.2のデーモンに各CLIイメージから接続したところ、docker:18.09(API 1.39)だけが次のエラーで失敗し、docker:19.03(API 1.40)、docker:20.10、gcr.io/cloud-builders/docker:latest(API 1.41)は通りました。
Error response from daemon: client version 1.39 is too old. Minimum supported API version is 1.40, please upgrade your client to a newer version
Docker 20.10のデーモンはもっと古いCLIも受け付けていたので、docker:18.09のような古いタグを固定しているcloudbuild.yamlは、切替の日に突然落ちます。Docker 29.0〜29.2では最小APIが1.44だったため、それらの版ならAPI 1.41のcloud-builders/dockerも拒否されます。29.3.0で1.40に引き下げられました(Docker Engine 29のリリースノート)。Cloud Buildは2026.09のDockerのパッチ番号を公開していないので、ステップのDocker CLIはAPI 1.44に対応したDocker 25.0以降のタグ(docker:25以降)にそろえ、regularで接続を確かめておくのが確実です。
regularチャネルでの切替前の検証
デフォルトプールなら、cloudbuild.yamlのoptionsにチャネルを書くか、実行時に--worker-releaseを付けます。コマンドラインの指定はビルド構成の指定より優先されます。
options:
workerRelease: regular
1回だけ試すなら、コマンドラインで指定します。
gcloud builds submit --region=asia-northeast1 --config cloudbuild.yaml --worker-release=regular
プライベートプールでは、ビルド構成やコマンドラインでチャネルを指定できません。gcloud builds worker-pools update POOL_ID --worker-release=regular --region=REGIONでプール側に設定し、そのプールで動く全ビルドに効かせます。切替日の前に本番と同じcloudbuild.yamlで1回流し、キャッシュの当たり方と所要時間を比べておきます。CI基盤の移行やパイプライン設計を外部に任せたい場合は、DevOps・CI/CD導入支援で相談を受けています。
Cloud Build APIによるビルドの起動と状態取得
CLIやトリガーを使わず、他のシステムから直接ビルドを起動するならREST APIを呼びます。エンドポイントはhttps://cloudbuild.googleapis.com/v1/projects/{projectId}/locations/{location}/buildsで、呼び出す側にはcloudbuild.builds.create権限が要ります。リージョンを含まない旧来のパス(projects/{projectId}/builds)はglobalリージョンにしかビルドを作れないので、リージョンを指定する形で呼びます(projects.builds.createのリファレンス)。
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://cloudbuild.googleapis.com/v1/projects/YOUR_PROJECT_ID/locations/asia-northeast1/builds" \
-d '{"steps":[{"name":"ubuntu","args":["echo","hello from api"]}]}'
レスポンスは長時間実行オペレーションで、metadata.build.idにビルドIDが入ります。状態はGET .../builds/{id}で取得し、:cancelで中止、:retryで再実行できます。既存のトリガーを外部から起動するならPOST .../triggers/{trigger}:runを使い、CLIではgcloud builds triggers runが同じ操作です。Python・Node.js・Goなどのクライアントライブラリも同じAPIを呼んでいます。
GitHub連携とビルドトリガー
トリガーで選べるイベント
ビルドトリガーは、イベントを検知して自動でビルドを始める仕組みです。リポジトリのイベントとして、ブランチへのpush、タグのpush、プルリクエストへのコミットを選べます。ほかに、画面やAPIから実行する手動トリガー、Pub/Subのメッセージで動くトリガー、外部のWebhookを受けて動くトリガーがあります(トリガーの作成と管理)。ブランチへのpushはmainマージ後の本番デプロイ、プルリクエストはマージ前のテスト、という分担が基本です。
gcloud builds triggers create github \
--name=deploy-main \
--region=asia-northeast1 \
--repository=projects/YOUR_PROJECT_ID/locations/asia-northeast1/connections/my-conn/repositories/my-repo \
--branch-pattern='^main$' \
--build-config=cloudbuild.yaml \
--service-account=projects/YOUR_PROJECT_ID/serviceAccounts/my-build-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
これは第2世代のリポジトリ接続を使う書き方です。トリガーの作成・更新ではサービスアカウントの指定が必須で、省略できるのはプロジェクトの既定がレガシーのCloud Buildサービスアカウントのときだけです(サービスアカウントの変更点)。
第2世代の接続とDeveloper Connectの違い
GitHub・GitLab・Bitbucketの接続方法は、Cloud Build repositories(第2世代)とDeveloper Connectの2つです。接続できるサービスは同じで、違いは起動できるトリガーの種類です(Cloud Buildのリポジトリ)。
| 機能 | 第2世代 | Developer Connect |
|---|---|---|
| push・タグ・PRでのビルド | ○ | ○ |
| 手動・Pub/Sub・Webhookトリガー | ○ | × |
| gcloudで接続を作成 | ○ | ○ |
手動やWebhookでの起動を使うなら第2世代を選びます。第1世代の接続は旧方式として残っているだけです。かつて定番だったCloud Source Repositoriesは、2024年6月17日以降、それまで使ったことのない組織と、組織に属さない新しいプロジェクトではAPIを有効化できません。それ以前から使っている組織は影響を受けず、停止日は少なくとも1年前に告知されます。GitLabとの併用を検討しているなら、GitHubとGitLabの違いも比べてみてください。
権限設計の落とし穴|実行サービスアカウントとログの出力先
既定のサービスアカウントの判定条件
2024年5〜6月の変更後に初めてビルドを実行したプロジェクトは、Compute Engineのデフォルトサービスアカウント([email protected])でビルドします。それより前から使っているプロジェクトは、レガシーのCloud Buildサービスアカウント([email protected])のままです。
レガシーSAを前提にした手順どおりにロールを付けても、実際に使われるのがCompute EngineのSAなら権限エラーは消えません。まずビルドの詳細画面で実行したサービスアカウントを確かめ、そのSAにロールを付けます。Artifact Registryへのpushにはroles/artifactregistry.writer、Cloud Runへのデプロイにはroles/run.developerと、デプロイ先のサービスアカウントへのroles/iam.serviceAccountUserが要ります。
ユーザー指定SAで必要なログ出力先の設定
Compute Engineのデフォルトサービスアカウントには、組織ポリシーiam.automaticIamGrantsForDefaultServiceAccountsが効いていない環境だと、作成時に編集者ロール(roles/editor)が付きます。このポリシーは2024年5月3日から組織で有効になっており、それ以降に作られたSAには付与されません。どちらにしても、実際のロールを確かめ、ビルド専用のSAに必要な権限だけを付けるのが安全です。Googleもユーザー指定のサービスアカウントを勧めています。ところが、ビルド専用のSAを作ってserviceAccountに指定すると、ビルドが始まらず次のエラーが返ります。
if 'build.service_account' is specified, the build must either
(a) specify 'build.logs_bucket',
(b) use the REGIONAL_USER_OWNED_BUCKET build.options.default_logs_bucket_behavior option,
or (c) use either CLOUD_LOGGING_ONLY / NONE logging options
ユーザー指定のサービスアカウントは、Cloud Buildが管理する既定のログバケットへ書き込めないためです。手間が少ないのはログをCloud Loggingへ寄せる方法です。
serviceAccount: 'projects/$PROJECT_ID/serviceAccounts/my-build-sa@$PROJECT_ID.iam.gserviceaccount.com'
options:
logging: CLOUD_LOGGING_ONLY
この場合、ビルド用SAにroles/logging.logWriterを付けます。ログをCloud Storageに残す決まりがあるなら、自分で作ったバケットをlogsBucketに指定してloggingをGCS_ONLYにし、そのバケットへの書き込み権限をSAに与えます。NONEは障害調査の手段を失うので避けてください。
GitHub Actionsとの使い分け|単価と選び方
2vCPUのLinux(x64)なら、単価はどちらも$0.006/分で同じです。差が出るのは上位マシンと無料枠です(GitHub Actionsのランナー単価)。
| 項目 | Cloud Build | GitHub Actions |
|---|---|---|
| 2vCPU Linux(x64) | $0.006/分(東京も同額) | $0.006/分 |
| 8vCPU Linux(x64) | $0.0156/分(東京$0.019968) | $0.022/分 |
| 無料枠 | 月2,500分(請求先アカウント単位) | 月2,000分(Free)・3,000分(Pro/Team)※標準ランナーのみ |
| 公開リポジトリ | 区別なく課金 | 標準ランナーは無料・大型ランナーは課金 |
デプロイ先がCloud RunやGKEなどGoogle Cloudに閉じているなら、Cloud Buildが有利です。ビルドを実行するサービスアカウントの権限だけでGoogle CloudのAPIを呼べるので、Workload Identity連携を設定したり鍵をGitHubのSecretsに置いたりする必要がなく、権限の管理がIAMにまとまります。8vCPUの単価もCloud Buildのほうが安くなります(ただしe2-highcpu-8のメモリは8GBで、GitHubの8-coreより少なめです)。
リポジトリがGitHubにあり、成果物をGoogle Cloud以外にも配る(npmへの公開、複数クラウドへのデプロイなど)なら、GitHub Actionsのほうが素直です。公開リポジトリなら標準ランナーは無料です(8-coreなどの大型ランナーは公開リポジトリでも課金され、プランの無料枠も使えません)。単価の細かい比較はGitHub Actionsの料金、ワークフローの組み方はGitHub Actionsでビルド・自動テストを設定する方法を見てください。「テストとレビューはGitHub Actions、mainマージ後の本番デプロイだけCloud Build」という併用は、テストを公開リポジトリの無料枠で回しつつ、本番デプロイの権限をIAMにまとめたいときに向きます。
Cloud Buildを選ぶべきでない場面もあります。複数のOSやバージョンの組み合わせ(ビルドマトリクス)を大量に回したいなら、Cloud Buildにはマトリクス機能がなく、組み合わせの数だけstepsを書き並べることになります。ビルドからVPC内のプライベートなリソース(プライベートIPのCloud SQLなど)へ接続したい場合も注意が要ります。デフォルトプールはGoogle管理の環境で動くのでユーザーのVPCには届かず、プライベートプールとVPCピアリングの構成が別途必要です。
よくある質問
Cloud Buildの無料枠はどれくらいですか?
請求先アカウントごとに月2,500ビルド分です。対象はデフォルトプールのe2-standard-2で、キュー待ちの時間は課金されません。1ビルド3分なら月833回程度まで収まります。公式はプロモーション枠であり変更されうると注記しています。
東京リージョンでビルドすると料金は高くなりますか?
既定のe2-standard-2は東京でもus-central1と同じ$0.006/分です。e2-mediumとe2-highcpu-8、e2-highcpu-32は東京のほうが28%高く、e2-highcpu-8は東京で$0.019968/分、us-central1で$0.0156/分です(2025年11月1日改定の料金表)。
ビルドが60分で止まるのはなぜですか?
timeoutの既定値が60分のためです。cloudbuild.yamlのトップレベルにtimeout: '7200s'のように秒数で指定すると延ばせます。上限は24時間です。
gcloud builds submitで$SHORT_SHAが空になるのはなぜですか?
COMMIT_SHAやSHORT_SHAはトリガー経由のビルドでしか設定されず、手動実行では空文字に置き換わります。--substitutions SHORT_SHA=$(git rev-parse --short HEAD)のように明示的に渡してください。
Cloud Source Repositoriesは今から使えますか?
2024年6月17日より前に使ったことのある組織なら使えます。利用実績の無い組織や、組織に属さない新しいプロジェクトではAPIを有効化できません。GitHubやGitLabを第2世代のリポジトリ接続かDeveloper Connectでつなぐか、Secure Source Managerを検討してください。
Container Registry(gcr.io)にpushできないのはなぜですか?
Container Registryは2025年3月18日に停止し、書き込みができません。Artifact Registryへ移行してください。Artifact Registry上にgcr.ioリポジトリを作れば、gcr.ioのURLのままpushでき、イメージはArtifact Registryに保存されます。
関連記事
- Cloud Runとは?GCPのサーバーレスコンテナの仕組み・料金とGKE/Cloud Functionsとの違いを実装者目線で解説
- Artifact Registryとは?Google Cloudの成果物リポジトリの仕組み・料金とContainer Registry移行を実装者目線で解説
- BuildKitとは|Dockerの新ビルドバックエンドの仕組み・キャッシュ/secret/マルチアーキと採用判断を実装者目線で解説
- GitHub Actionsでビルド・自動テストを設定する方法|build.ymlの書き方と失敗の直し方
- Dockerfileとは|書き方・主要命令・ベストプラクティスを解説【2026年版】