【GCP × Claude Code】低コスト&完全自動化!GCPコンテナ環境とClaude Code連携CI/CDの構築手順まとめ

タグ: 個人開発 / GCP / Cloud Run / Claude Code / CI/CD

【GCP × Claude Code】低コスト&完全自動化!GCPコンテナ環境とClaude Code連携CI/CDの構築手順まとめ

個人開発で待機コストを「完全ゼロ」に抑えつつ、GitHub Issueから自動でコード生成&デプロイまで繋がるモダンなインフラ基盤を構築しました。

こんにちは!個人開発で「コストは最小限に、開発スピードと品質は最大限に」を目標に日々構成を捏ねくり回しているエンジニアです。

今回は、GCP(Cloud Run) 上にサーバーレス&マイクロサービス構成をゼロから立ち上げ、さらに Claude CodeGitHub Actions を組み合わせて「Issueに要望を書くだけで実装・PR生成・自動デプロイまで完結する環境」を自作・構築した全手順を詳しく解説します!

1. 全体構成・アーキテクチャ

全体のシステム構成は以下の通りです。個人開発での待機コストを完全ゼロにするため、サーバーレスコンポーネントを中心に設計しました。

コンポーネント 役割・選定理由
Cloud Run (サービス) FastAPIで作ったWeb/API基盤。リクエストなし時は0台にスケールするため待機コストなし。
Cloud Run Jobs バッチ処理基盤。Cloud Schedulerからの定期実行や手動実行に対応。
Artifact Registry Web/バッチ用のDockerイメージ保存用リポジトリ(app-images)。
Workload Identity Federation Service Account Keyを使わず、GitHub ActionsからGCPへ安全にキーレス認証。
GitHub Actions PRでの差分テスト(CI)およびmainマージ時の安全デプロイ(CD)。
Claude Code (GitHub App) Issue/PRの @claude コメントを検知し、自律的にコード実装・PR作成・リファクタを実施。

2. GCP基盤・Workload Identity Federationの設定手順

まずはGCP側の準備を行います。サービスアカウントキーの発行を避け、セキュリティを高めるために Workload Identity Federation (WIF) をセットアップします。

ステップ1:必要なAPIの有効化

gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  iamcredentials.googleapis.com \
  cloudscheduler.googleapis.com \
  secretmanager.googleapis.com

ステップ2:Artifact Registryリポジトリとデプロイ用SAの作成

# リポジトリ作成
gcloud artifacts repositories create app-images \
  --repository-format=docker \
  --location=asia-northeast1

# サービスアカウント作成
gcloud iam service-accounts create gh-deployer \
  --display-name="GitHub Actions Deployer"

# 必要な権限の付与
PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:gh-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:gh-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/artifactregistry.writer"
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:gh-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/iam.serviceAccountUser"

ステップ3:Workload Identity Pool & Provider の構築

# プールの作成
gcloud iam workload-identity-pools create "github-pool" \
  --location="global" \
  --display-name="GitHub Actions Pool"

# プロバイダの作成
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --location="global" \
  --workload-identity-pool="github-pool" \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository"

# GitHubリポジトリからのアクセスを許可
gcloud iam service-accounts add-iam-policy-binding "gh-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')/locations/global/workloadIdentityPools/github-pool/attribute.repository/YOUR_GITHUB_USER/sample-app"

3. プロジェクトディレクトリ&サービス実装

将来的な機能拡張を見据え、Webアプリとバッチ処理をマルチサービス(モノリポ風)構成に整理しました。

sample-app/
├─ CLAUDE.md                     # Claude Code用のプロジェクト文脈ガイド
├─ README.md                     # プロジェクト仕様と設定方法
├─ infra/setup.sh                # インフラ初期化スクリプト
├─ services/
│   ├─ web/                      # Web/APIサービス(FastAPI)
│   │   ├─ app/main.py
│   │   ├─ tests/test_main.py
│   │   ├─ requirements.txt / requirements-dev.txt
│   │   ├─ pyproject.toml        # ruff / mypy / pytest設定
│   │   └─ Dockerfile
│   └─ batch/                    # バッチ処理(Pythonスクリプト)
│       ├─ job/main.py
│       ├─ tests/test_main.py
│       └─ Dockerfile
└─ .github/workflows/
    ├─ ci.yml
    ├─ deploy.yml
    └─ claude.yml

FastAPI Webサービスの実装例 (services/web/app/main.py)

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, sample-app!"}

@app.get("/healthz")
def healthz():
    return {"status": "ok"}

4. GitHub Actions CI/CD パイプラインの作成

① PR時の差分検知CI (.github/workflows/ci.yml)

dorny/paths-filter を使用して、変更があったサービスのみ ruffmypypytest を実行します。

name: CI

on:
  pull_request:
    branches: [ main ]

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      web: ${{ steps.filter.outputs.web }}
      batch: ${{ steps.filter.outputs.batch }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            web: 'services/web/**'
            batch: 'services/batch/**'

  test-web:
    needs: changes
    if: ${{ needs.changes.outputs.web == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install -r services/web/requirements-dev.txt
      - run: ruff check services/web
      - run: mypy services/web
      - run: pytest services/web/tests

② ゼロトラフィックデプロイCD (.github/workflows/deploy.yml)

FastAPI(Web)デプロイ時は、一度 --no-traffic でデプロイしてからヘルスチェック(/healthz)を通過した後にトラフィックを100%割り当てることで、無停止&安全なデプロイを実現しました。

name: Deploy

on:
  push:
    branches: [ main ]

jobs:
  deploy-web:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
          service_account: ${{ secrets.DEPLOY_SA_EMAIL }}
      - uses: google-github-actions/setup-gcloud@v2

      - name: Build & Push
        run: |
          gcloud auth configure-docker asia-northeast1-docker.pkg.dev
          docker build -t asia-northeast1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/app-images/web:${{ github.sha }} services/web
          docker push asia-northeast1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/app-images/web:${{ github.sha }}

      - name: Deploy to Cloud Run (No Traffic)
        run: |
          gcloud run deploy sample-web \
            --image asia-northeast1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/app-images/web:${{ github.sha }} \
            --region asia-northeast1 \
            --no-traffic

      - name: Smoke Test & Traffic Switch
        run: |
          # 簡易スモークテスト実施後、成功なら100%切り替え
          gcloud run services update-traffic sample-web --region asia-northeast1 --to-latest

5. Claude Code CLI & GitHub Actions連携の設定

GitHub上で @claude ○○を実装して と書くだけで自動開発を進めてもらうための設定です。

ステップ1:GitHub Appの連携とSecretsの設定

  • GitHub App「Claude」をリポジトリにインストールします。
  • GitHub Secrets に以下を登録します:
    • GCP_PROJECT_ID : GCPプロジェクトID
    • DEPLOY_SA_EMAIL : サービスアカウントのメールアドレス
    • WIF_PROVIDER : Workload Identity Providerのフルパス
    • CLAUDE_CODE_OAUTH_TOKEN : ローカルで claude setup-token を実行して発行されたOAuthトークン

ステップ2:Claude Code用ワークフロー (.github/workflows/claude.yml)

name: Claude Code Action

on:
  issues:
    types: [opened, labeled]
  issue_comment:
    types: [created]

jobs:
  claude:
    if: contains(github.event.comment.body, '@claude') || contains(github.event.issue.body, '@claude')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: anthropics/claude-code-action@v1
        with:
          claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

6. 実際に動かしてみた&まとめ

実際にGitHub Issueを作成し、@claude READMEの記述をチェックして と指示を投げてテストしました。

テスト結果:わずか42秒で解析完了!

タイポの有無だけでなく、「READMEに記載されているAPIキー認証と、実際の claude.yml で使われているOAuthトークン認証の記述がズレています」という矛盾まで正確に指摘・修正PRを提示してくれました。

この構成のメリットは以下の通りです:

  • 完全待機コストゼロ: Cloud Runの0台スケールにより、使っていない時間は費用が発生しない。
  • 開発速度の劇的向上: Issueで依頼するだけでClaudeが自律的にコードを書いてPRを作成。
  • 高い安全性: WIFによるキーレス認証とスモークテスト付きのゼロトラフィックデプロイ。

個人開発のインフラ設計や自動化に悩んでいる方は、ぜひ参考にしてみてください!

コメント

タイトルとURLをコピーしました