Google Cloud BuildでCI/CD構築|ビルド・テスト・デプロイの自動化実践

kento_morota 21分で読めます

コードの変更を安全かつ迅速にデプロイするために、CI/CD(継続的インテグレーション/継続的デリバリー)パイプラインの構築は現代の開発プロセスにおいて不可欠です。

Google Cloud Buildは、GCPが提供するフルマネージドのCI/CDプラットフォームです。この記事では、Cloud Buildの基本概念から、ビルド構成ファイルの作成、テストの自動実行、Cloud Runへのデプロイ自動化まで、実務で使えるCI/CDパイプラインの構築手順を詳しく解説します。

Cloud Buildとは?GCPのCI/CDサービスの全体像

Cloud Buildは、ソースコードのビルド、テスト、デプロイをサーバーレスで実行するCI/CDサービスです。Jenkins等のCIサーバーを自前で構築・管理する必要がなく、使った分だけ課金される従量課金モデルで利用できます。

Cloud Buildの特徴

  • サーバーレス:ビルドサーバーの管理が不要。スケーリングもGCPが自動で行う
  • 高速ビルド:カスタムマシンタイプを選択可能。最大32vCPU、256GBメモリまでスケールアップできる
  • GitHubとの連携:GitHub、Bitbucket、Cloud Source Repositoriesのプッシュやプルリクエストをトリガーにビルドを実行
  • Docker対応:各ステップはDockerコンテナとして実行されるため、任意のツールやランタイムを利用可能
  • GCPサービスとのネイティブ統合Artifact Registry、Cloud Run、GKEなどとシームレスに連携

料金体系

Cloud Buildの料金は、ビルド時間に基づいて課金されます。

  • 無料枠:1日あたり120分のビルド時間(e2-medium相当)
  • e2-medium:$0.003/ビルド分
  • e2-highcpu-8:$0.016/ビルド分
  • e2-highcpu-32:$0.064/ビルド分

小規模なプロジェクトであれば、無料枠内で十分に運用可能です。

Cloud Buildの基本設定とcloudbuild.yaml

Cloud Buildのパイプラインは、cloudbuild.yamlファイルで定義します。このファイルがCI/CDの設計図となります。

APIの有効化と初期設定

# Cloud Build APIの有効化
gcloud services enable cloudbuild.googleapis.com

# Artifact Registry APIの有効化(イメージプッシュに必要)
gcloud services enable artifactregistry.googleapis.com

cloudbuild.yamlの基本構造

最もシンプルなビルド構成ファイルの例です。

# cloudbuild.yaml
steps:
  # ステップ1: 依存パッケージのインストール
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['ci']

  # ステップ2: リントの実行
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['run', 'lint']

  # ステップ3: テストの実行
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['test']

  # ステップ4: Dockerイメージのビルド
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'
      - '.'

# ビルドしたイメージをArtifact Registryにプッシュ
images:
  - 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'

主要な設定項目の解説

steps:ビルドの各ステップを定義します。デフォルトでは順番に実行されます。

name:ステップを実行するDockerイメージ。gcr.io/cloud-builders/以下にGCPが提供する公式ビルダーが用意されています。

substitutions(変数):ビルド時に利用できる変数です。

  • $PROJECT_ID:GCPプロジェクトID
  • $BUILD_ID:ビルドの一意なID
  • $COMMIT_SHA:完全なコミットハッシュ
  • $SHORT_SHA:短縮コミットハッシュ(先頭7文字)
  • $BRANCH_NAME:ブランチ名
  • $TAG_NAME:タグ名

ビルドトリガーの設定

ビルドトリガーは、ソースコードの変更を検知してCloud Buildを自動的に起動する仕組みです。

GitHubリポジトリとの接続

# GitHub接続の作成(Cloud Consoleで行うのが最も簡単)
# 「Cloud Build」→「トリガー」→「リポジトリを接続」から設定

# CLI で GitHub 第2世代接続を作成する場合
gcloud builds connections create github my-github-connection \
  --region=asia-northeast1

プッシュトリガーの作成

# mainブランチへのプッシュでビルドを実行するトリガー
gcloud builds triggers create github \
  --name="deploy-production" \
  --repository=projects/my-project/locations/asia-northeast1/connections/my-github-connection/repositories/my-repo \
  --branch-pattern="^main$" \
  --build-config="cloudbuild.yaml" \
  --region=asia-northeast1 \
  --description="mainブランチへのプッシュで本番デプロイ"

# developブランチへのプッシュでテストのみ実行するトリガー
gcloud builds triggers create github \
  --name="test-develop" \
  --repository=projects/my-project/locations/asia-northeast1/connections/my-github-connection/repositories/my-repo \
  --branch-pattern="^develop$" \
  --build-config="cloudbuild-test.yaml" \
  --region=asia-northeast1 \
  --description="developブランチへのプッシュでテスト実行"

プルリクエストトリガー

プルリクエストが作成・更新されたときにテストを実行するトリガーも設定できます。

# PRトリガーの作成
gcloud builds triggers create github \
  --name="pr-check" \
  --repository=projects/my-project/locations/asia-northeast1/connections/my-github-connection/repositories/my-repo \
  --pull-request-pattern="^main$" \
  --build-config="cloudbuild-pr.yaml" \
  --region=asia-northeast1 \
  --comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY

PR用のビルド構成ファイルでは、デプロイは行わずテストとリントのみを実行するようにします。

実践的なCI/CDパイプラインの構築

ここからは、実務で使える実践的なパイプライン構成を紹介します。

マルチステージビルドの最適化

# cloudbuild.yaml - 本番デプロイ用
steps:
  # ステップ1: 依存パッケージのインストール(キャッシュ活用)
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['ci', '--prefer-offline']
    id: 'install'

  # ステップ2: リントとテストを並列実行
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['run', 'lint']
    id: 'lint'
    waitFor: ['install']

  - name: 'node:20'
    entrypoint: 'npm'
    args: ['test', '--', '--coverage']
    id: 'test'
    waitFor: ['install']

  # ステップ3: Dockerイメージのビルド(リントとテスト完了後)
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'
      - '-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'
      - '.'
    id: 'build'
    waitFor: ['lint', 'test']

  # ステップ4: Cloud Runへのデプロイ
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - 'run'
      - 'deploy'
      - 'my-service'
      - '--image=asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'
      - '--region=asia-northeast1'
      - '--platform=managed'
      - '--quiet'
    id: 'deploy'
    waitFor: ['build']

images:
  - 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'
  - 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:latest'

options:
  machineType: 'E2_HIGHCPU_8'
  logging: CLOUD_LOGGING_ONLY

timeout: '1200s'

ポイントは、waitForidを使ってステップの並列実行を制御していることです。リントとテストは依存関係がないため並列に実行でき、ビルド全体の所要時間を短縮できます。

Secret Managerとの連携

APIキーやデータベースパスワードなどの機密情報は、Secret Managerに保存してビルド時に参照します。

# Secret Managerにシークレットを作成
echo -n "my-database-password" | gcloud secrets create db-password --data-file=-

# cloudbuild.yamlでシークレットを参照
steps:
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['run', 'migrate']
    secretEnv: ['DB_PASSWORD']

availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/db-password/versions/latest
      env: 'DB_PASSWORD'

Cloud Runへの段階的デプロイ

Cloud Runへのデプロイでは、カナリアリリースやブルーグリーンデプロイを活用することで、デプロイのリスクを最小限に抑えられます。

トラフィック分割によるカナリアリリース

# cloudbuild-canary.yaml
steps:
  # イメージのビルド
  - 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/gcloud'
    args:
      - 'run'
      - 'deploy'
      - 'my-service'
      - '--image=asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'
      - '--region=asia-northeast1'
      - '--no-traffic'
      - '--tag=canary'
      - '--quiet'

  # カナリアリビジョンに10%のトラフィックを割り当て
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - 'run'
      - 'services'
      - 'update-traffic'
      - 'my-service'
      - '--region=asia-northeast1'
      - '--to-tags=canary=10'

images:
  - 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'

カナリアリリース後、Cloud Monitoringでエラーレートやレイテンシを確認し、問題がなければ100%に切り替えます。

# 問題なければ全トラフィックを新リビジョンに切り替え
gcloud run services update-traffic my-service \
  --region=asia-northeast1 \
  --to-latest

# 問題があればカナリアをロールバック
gcloud run services update-traffic my-service \
  --region=asia-northeast1 \
  --to-tags=canary=0

デプロイ後の自動ヘルスチェック

デプロイ直後に自動的にヘルスチェックを行い、失敗時はロールバックするステップを追加できます。

# ヘルスチェックステップ
  - name: 'gcr.io/cloud-builders/curl'
    args:
      - '-f'
      - '-s'
      - '-o'
      - '/dev/null'
      - '-w'
      - '%{http_code}'
      - 'https://canary---my-service-xxxxx.a.run.app/health'
    id: 'health-check'
    waitFor: ['deploy-canary']

ビルドの高速化テクニック

CI/CDパイプラインの実行時間は、開発チームの生産性に直結します。以下のテクニックでビルドを高速化しましょう。

Dockerレイヤーキャッシュの活用

Artifact Registryに保存された既存のイメージをキャッシュとして利用します。

# Dockerfile - マルチステージビルドとキャッシュ最適化
FROM node:20-slim AS builder

WORKDIR /app

# パッケージファイルのみ先にコピー(キャッシュ効率を向上)
COPY package*.json ./
RUN npm ci --prefer-offline

# ソースコードをコピーしてビルド
COPY . .
RUN npm run build

# 本番イメージ
FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./

CMD ["node", "dist/index.js"]

package*.jsonを先にコピーしてからnpm ciを実行することで、依存パッケージに変更がない場合はキャッシュが再利用されます。

Kaniko による高速ビルド

# Kanikoを使ったビルド(キャッシュが効率的)
steps:
  - name: 'gcr.io/kaniko-project/executor:latest'
    args:
      - '--destination=asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA'
      - '--cache=true'
      - '--cache-ttl=168h'
      - '--cache-repo=asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app-cache'

並列テスト実行

テストスイートを分割して並列実行することで、テストの実行時間を大幅に短縮できます。

# テストを並列実行
steps:
  - name: 'node:20'
    entrypoint: 'npm'
    args: ['ci']
    id: 'install'

  - name: 'node:20'
    entrypoint: 'npm'
    args: ['run', 'test:unit']
    id: 'unit-test'
    waitFor: ['install']

  - name: 'node:20'
    entrypoint: 'npm'
    args: ['run', 'test:integration']
    id: 'integration-test'
    waitFor: ['install']

  - name: 'node:20'
    entrypoint: 'npm'
    args: ['run', 'test:e2e']
    id: 'e2e-test'
    waitFor: ['install']

セキュリティとガバナンスの設定

CI/CDパイプラインは、コードから本番環境までの経路であるため、セキュリティの確保が極めて重要です。

サービスアカウントの最小権限設定

Cloud Buildのデフォルトサービスアカウントは広範な権限を持つ場合があるため、専用のサービスアカウントを作成して最小権限を付与しましょう。

# CI/CD用サービスアカウントの作成
gcloud iam service-accounts create cloud-build-cicd \
  --display-name="Cloud Build CI/CD"

# 必要な権限のみ付与
gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:cloud-build-cicd@my-project.iam.gserviceaccount.com" \
  --role="roles/artifactregistry.writer"

gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:cloud-build-cicd@my-project.iam.gserviceaccount.com" \
  --role="roles/run.developer"

gcloud projects add-iam-policy-binding my-project \
  --member="serviceAccount:cloud-build-cicd@my-project.iam.gserviceaccount.com" \
  --role="roles/iam.serviceAccountUser"

# トリガーにサービスアカウントを設定
gcloud builds triggers update deploy-production \
  --service-account=projects/my-project/serviceAccounts/cloud-build-cicd@my-project.iam.gserviceaccount.com \
  --region=asia-northeast1

IAMのセキュリティ設計をCI/CDパイプラインにも適用することが重要です。

プライベートプールの利用

VPCネットワーク内のリソースにアクセスする必要がある場合は、プライベートプールを使用します。

# プライベートプールの作成
gcloud builds worker-pools create my-private-pool \
  --region=asia-northeast1 \
  --peered-network=projects/my-project/global/networks/my-production-vpc \
  --worker-machine-type=e2-standard-4 \
  --worker-disk-size=100

ビルドの承認ゲート

本番デプロイ前に手動承認を要求するフローも設定可能です。

# cloudbuild.yaml - 承認ゲート付き
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/my-repo/my-app:$SHORT_SHA', '.']

  # 承認待ちステップ(Cloud Console上で承認操作が必要)
  - name: 'gcr.io/cloud-builders/gcloud'
    args: ['run', 'deploy', 'my-service', '--image=...', '--region=asia-northeast1']

options:
  pool:
    name: 'projects/my-project/locations/asia-northeast1/workerPools/my-private-pool'

まとめ:Cloud Buildで信頼性の高いCI/CDを実現する

Google Cloud Buildを使ったCI/CDパイプラインの構築方法を解説しました。重要なポイントをまとめます。

  • cloudbuild.yaml:パイプラインをコードとして管理し、waitForでステップの並列実行を最適化する
  • ビルドトリガー:ブランチごとにトリガーを分け、テスト用と本番デプロイ用を区別する
  • カナリアリリース:Cloud Runのトラフィック分割で段階的デプロイを実現する
  • ビルド高速化:Dockerレイヤーキャッシュ、Kaniko、並列テストでビルド時間を短縮する
  • セキュリティ:専用サービスアカウントとSecret Managerで機密情報を安全に管理する

まずはシンプルなcloudbuild.yamlを作成し、GitHubへのプッシュでテストが自動実行されるところから始めてみてください。パイプラインは段階的に拡充し、Artifact Registryへのイメージ保存、Cloud Runへの自動デプロイと進めていくのが現実的です。インフラ構成そのものをTerraformでコード管理すれば、CI/CDパイプラインとインフラの両方をバージョン管理できる体制が整います。

#GCP#Cloud Build#CI/CD
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

AI活用のヒントをお探しですか?お気軽にご相談ください。

まずは話だけ聞いてもらう