ゼロから本番環境までの Cloud Run の究極のガイド(デモのチュートリアル)

1. はじめに

この Codelab では、Cloud Run の基本的な使い方について説明します。Cloud Run でホストされている AI エージェントの VPC アクセス、Secret Manager、ADK などの追加機能の使用方法について説明します。

学習内容

  • nginx イメージをデプロイする
  • ソースコードからデプロイする
  • デプロイをロールバックする
  • デプロイをプレビューする
  • Developer Knowledge MCP サーバーツールを使用する
  • Cloud Run で Secret Manager を使用する
  • VPC 内の内部 Cloud Run サービスに接続する
  • ADK エージェントを Cloud Run にデプロイする

必要なもの

  • ウェブブラウザ(Chrome など)
  • 課金を有効にした Google Cloud プロジェクト

Google Cloud プロジェクトの作成

  1. Google Cloud コンソールのプロジェクト セレクタ ページで、Google Cloud プロジェクトを選択または作成します。
  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

Cloud Shell の起動

Cloud Shell は、必要なツールがプリロードされた Google Cloud で動作するコマンドライン環境です。

  1. Google Cloud コンソールの上部にある [Cloud Shell をアクティブにする] をクリックします。
  2. Cloud Shell に接続したら、認証を確認します。
    gcloud auth list
    
  3. プロジェクトが構成されていることを確認します。
    gcloud config get project
    
  4. プロジェクトが想定どおりに設定されていない場合は、設定します。
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

環境変数の設定

この Codelab では、次の環境変数を使用します。

まず、リージョンを設定します。

export REGION=<YOUR_REGION>

次に、PROJECT_ID と REGION を確認します。

echo "PROJECT_ID: $PROJECT_ID | REGION: $REGION"

2. イメージからデプロイする

このセクションでは、Docker Hub から標準の nginx イメージを直接デプロイします。一般公開アクセス可能になるように構成し、コンテナポートを 80 に設定します。

  1. nginx サービスをデプロイします。
   gcloud run deploy nginx-service \
     --image=nginx \
     --allow-unauthenticated \
     --port=80 \
     --region=$REGION
  1. デプロイが完了すると、コマンド出力にサービス URL が表示されます。ブラウザでその URL を開くと、「Welcome to nginx!」ページが表示されます。

3. ソースからデプロイする

mkdir color-app && cd $_

次の内容のファイルを、requirements.txt という名前で作成します。

Flask>=2.0.0
gunicorn>=20.0.0

次の内容のファイルを、main.py という名前で作成します。

import os
from flask import Flask, render_template_string

app = Flask(__name__)

TEMPLATE = """
<!doctype html>
<html lang="en">
<head>
    <title>Cloud Run Traffic Revisions</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 50vh;
            background-color: darkseagreen;
            font-family: sans-serif;
        }
        .content {
            background-color: rgba(255, 255, 255, 0.8); /* Semi-transparent white background */
            padding: 2em;
            border-radius: 8px;
            text-align: center;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
    </style>
</head>
<body>
    <div class="content">
	  <!-- ROLLBACK DEMO: change this text to "gray" -->
        <p>background color: <strong>darkseagreen</strong></p>
    </div>
</body>
</html>
"""

@app.route('/')
def main():
    
    return render_template_string(TEMPLATE)

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 8080))
    app.run(debug=True, host='0.0.0.0', port=port)

そこで、次のコマンドを実行します。

gcloud run deploy \
 --allow-unauthenticated
 --region $REGION

4. ロールバックとプレビュー リンク

このセクションでは、バグを導入し、修正を調査しながら以前のリビジョンにロールバックする方法を学びます。

  1. まず、バグが含まれていないため、現在トラフィックを処理しているリビジョンの名前を記録します。
GOOD_REVISION=$(gcloud run revisions list --service color-app \
  --region $REGION --format 'value(REVISION)')
  1. color-app の main.py ファイル内で「ROLLBACK DEMO」を検索し、行を次のように更新します。
<p>background color: <strong>gray</strong></p>
  1. gcloud run deploy を再実行します。以前の構成がどのように使用されたかを確認します。

バグをデプロイしたので、ソースに戻って変更するか、git revert を実行してからビルド、新しいビルドのトリガーなどを行うことができます。ただし、その過程でエラーが発生する可能性があります。

より安全な方法は、ロールバックを行うことです。

  1. 以前のリビジョンにロールバックするには、次のコマンドを実行します。
gcloud run services update-traffic color-app \
  --to-revisions=$GOOD_REVISION=100 \
  --region=$REGION

これで、トラフィックを受信しない新しいリビジョンをデプロイできます。

  1. テキストを darkseagreen に戻してバグを修正します。
<p>background color: <strong>darkseagreen</strong></p>
  1. そして、修正を検証するためにデプロイします。トラフィックの 100% が GOOD_REVISION に固定されているため、トラフィックは受信されません。
gcloud run deploy color-app --no-traffic --tag bugfix --region $REGION
  1. デプロイを確認する

URL が少し異なることに気づくでしょう。アクセスすると、このデプロイにバグの修正が表示されます。

  1. トラフィックを最新のリビジョンに送り返します。

次に、トラフィックを最新のリビジョンに戻します。

gcloud run services update-traffic color-app \
  --to-latest \
  --region=$REGION

リビジョンのタグを削除します。

gcloud run services update-traffic color-app \
  --remove-tags=bugfix \
  --region=$REGION

ロールバックの詳細については、ドキュメントをご覧ください。

5. Developer Knowledge MCP サーバー

Developer Knowledge MCP サーバーを使用すると、AI を搭載した開発ツールで Google の公式デベロッパー ドキュメントを検索し、Firebase、Google Cloud、Android、マップなどの Google プロダクトの情報を取得できるようになります。AI アプリケーションを Google の公式ドキュメント ライブラリに直接接続することで、受け取るコードとガイダンスが最新のものであり、信頼できるコンテキストに基づいていることを保証できます。

AI エージェントに Developer Knowledge MCP サーバーへのアクセス権を付与するには、インストール ガイダンスに従ってください。

インストールが完了すると、モデルのトレーニング日のカットオフ後に利用可能になった可能性があるドキュメントの最新機能について、AI エージェントに質問できます。

たとえば、Cloud Run のリリースノートを見ると、2026 年 2 月 24 日に「Cloud Run サービスの健全性(プレビュー版)を使用して、外部トラフィックの自動フェイルオーバーとフェイルバックを備えた高可用性のマルチリージョン Cloud Run サービスをデプロイする」というエントリがあります。

AI エージェントに「マルチリージョン自動フェイルオーバー用のこの新しい Cloud Run 機能について詳しく教えて」と質問できるようになりました。

6. Secret Manager の使用

Cloud Run でシークレットを公開する方法は 3 つあります。

  1. 環境変数として(デプロイ時に取得されたバージョンにロックされます)。
  2. ファイル ボリュームとしてマウント(最新バージョンに継続的に更新)。
  3. コードで Secret Manager クライアント ライブラリを使用する。

このセクションでは、専用のサービス アカウントを使用してシークレットを環境変数として公開します。

  1. 「my-secret」という名前の新しいシークレットを作成します。
gcloud secrets create my-secret --replication-policy="automatic"
  1. シークレット値を新しいバージョンとして追加します。
echo -n "my precious" | gcloud secrets versions add my-secret --data-file=-
  1. color-app 専用のサービス アカウントを作成します。
gcloud iam service-accounts create color-app-sa \
     --display-name="Color App Service Account"
  1. 専用のサービス アカウントにシークレットへのアクセス権を付与します。
   gcloud secrets add-iam-policy-binding my-secret \
     --member="serviceAccount:color-app-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
     --role="roles/secretmanager.secretAccessor"
  1. 再度デプロイします。これで、サービスは MY_SECRET 環境変数にアクセスできるようになります。
gcloud run deploy color-app \
     --source . \
     --update-secrets=MY_SECRET=my-secret:latest \
     --service-account=color-app-sa@${PROJECT_ID}.iam.gserviceaccount.com \
     --region=$REGION

7. VPC に接続する

このセクションでは、次のアーキテクチャを設定します。

  • 公共のインターネットからアクセスできないプライベート バックエンド
  • ダイレクト VPC 下り(外向き)を介してバックエンドと通信するパブリック フロントエンド

この例では、デフォルトのネットワークとサブネットを使用します。

前提条件: VPC が内部リクエストを Cloud Run サービスに転送できるように、サブネットでプライベート Google アクセスが有効になっていることを確認します。

   gcloud compute networks subnets update default \
     --region=$REGION \
     --enable-private-ip-google-access
  1. このセクションのフォルダを作成する
mkdir ../vpc-demo
cd ../vpc-demo
  1. 限定公開バックエンド サービスを作成する
mkdir backend
touch backend/app.js
touch backend/package.json

backend/app.js ファイルに以下を追加します。

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World from the Private Backend!');
});

const port = process.env.PORT || 8080;
server.listen(port, () => {
  console.log(`Private backend listening on port ${port}`);
});

backend/package.json ファイルに以下を追加します。

{
    "name": "backend",
    "scripts": {
        "start": "node app.js"
    }
}
  1. 内部専用の Ingress を使用してプライベート バックエンドをデプロイします。
   gcloud run deploy private-backend \
     --source ./backend \
     --region $REGION \
     --ingress internal \
     --no-allow-unauthenticated
  1. バックエンド URL をメモしておきます。この URL は、後でフロントエンド アプリに提供します。
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projec
tNumber)')

export BACKEND_URL="https://private-backend-${PROJECT_NUMBER}.${REGION}.run.app"
  1. フロントエンド アプリを作成する
mkdir frontend
touch frontend/app.js
touch frontend/package.json

frontend/app.js ファイルに以下を追加します。

const http = require('http');

const server = http.createServer(async (req, res) => {
  const backendUrl = process.env.BACKEND_URL;
  
  if (!backendUrl) {
    res.writeHead(500, { 'Content-Type': 'text/plain' });
    return res.end('Error: BACKEND_URL environment variable is missing.');
  }

  try {
    // Fetch the OIDC token from the Metadata server
    const tokenResponse = await fetch(`http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=${backendUrl}`, {
      headers: { 'Metadata-Flavor': 'Google' }
    });

    if (!tokenResponse.ok) {
      throw new Error(`Failed to fetch identity token: ${tokenResponse.statusText}`);
    }
    const token = await tokenResponse.text();

    // Ping the backend with the token
    const response = await fetch(backendUrl, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
    const text = await response.text();

    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end(`Frontend successfully routed through VPC. Backend says: "${text}"`);
  } catch (error) {
    res.writeHead(500, { 'Content-Type': 'text/plain' });
    res.end(`Frontend failed to reach the backend. Error: ${error.message}`);
  }
});

const port = process.env.PORT || 8080;
server.listen(port, () => {
  console.log(`Public frontend listening on port ${port}`);
});
  1. frontend/package.json ファイルに以下を追加します。
{
    "name": "backend",
    "scripts": {
        "start": "node app.js"
    }
}
  1. フロントエンド サービス専用のサービス アカウントを作成します。
  gcloud iam service-accounts create frontend-sa \
     --display-name="Frontend Service Account"
  1. Cloud Run 起動元ロールを付与する
PROJECT_ID=$(gcloud config get project)
  
gcloud projects add-iam-policy-binding $PROJECT_ID \
     --member="serviceAccount:frontend-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
     --role="roles/run.invoker"
  1. 次に、ダイレクト VPC 下り(外向き)を使用してパブリック フロントエンドをデプロイします。送信リクエストを VPC に強制的に転送するために、次のように「--vpc-egress=all-traffic」を設定します。
   gcloud run deploy public-frontend \
     --source ./frontend \
     --region $REGION \
     --allow-unauthenticated \
     --network default \
     --subnet default \
     --vpc-egress all-traffic \
    --service-account=frontend-sa@${PROJECT_ID}.iam.gserviceaccount.com \
     --set-env-vars BACKEND_URL=$BACKEND_URL
  1. サービスを確認する
  • フロントエンドをテストする: 公開フロントエンド URL を curl します。バックエンドと正常に通信し、レスポンスを返します。
     FRONTEND_URL=$(gcloud run services describe public-frontend --region $REGION --format='value(status.url)')
     curl $FRONTEND_URL
  • バックエンドをテストする(直接): ローカルマシン(公共のインターネット)からバックエンド URL を直接 curl します。上り(内向き)は「internal」に制限され、認証が必要なため、404 エラーで失敗します。
  curl $BACKEND_URL

8. ADK エージェントをデプロイする

このセクションでは、Python Buildpack が Agent Development Kit(ADK)のデフォルト エントリ ポイントの検出をサポートする方法について説明します。

次のフォルダ構造を作成します。

adk-demo
 - my_agent
   - __init.py__
   - agent.py
 - requirements.txt
  1. フォルダ構造を作成する
mkdir ../adk-demo
cd ../adk-demo
mkdir my_agent
touch my_agent/__init.py__
touch my_agent/agent.py
touch requirements.txt
  1. my_agent/__init.py__ ファイルに次の内容を追加します。
from . import agent
  1. my_agent/agent.py ファイルに次の内容を追加します。
from google.adk import Agent

root_agent = Agent(
    name="demo_agent",
    model="gemini-3-flash-preview",
    instruction="You are a helpful assistant for a Cloud Run demo."
)
  1. requirements.txt ファイルに次の内容を追加します。
google-adk
  1. エージェント専用のサービス アカウントを作成します。
  gcloud iam service-accounts create agent-sa \
     --display-name="Agent Service Account"
  1. サービス アカウントに Vertex AI ユーザーロールを付与します。
PROJECT_ID=$(gcloud config get-value project)
  
gcloud projects add-iam-policy-binding $PROJECT_ID \
     --member="serviceAccount:agent-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
     --role="roles/aiplatform.user"
  1. ADK エージェントをデプロイする

Gemini API にアクセスできるリージョンにデプロイする必要があります。この例では、us-west1 です。

gcloud run deploy my-adk-agent-demo \
   --source . \
   --region us-west1 \
   --allow-unauthenticated \
   --service-account=agent-sa@${PROJECT_ID}.iam.gserviceaccount.com \
   --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=$PROJECT_ID,GOOGLE_CLOUD_LOCATION=global"
  1. エンドポイントを curl する

エージェントがプロダクション レディの API としてすぐに利用可能になっていることがわかります。

Cloud Run サービスの URL を環境変数に記録します。

AGENT_URL=$(gcloud run services describe my-adk-agent-demo \
  --region us-west1 \
  --format 'value(status.url)')

エージェントとのセッションを作成する

curl -X POST $AGENT_URL/apps/my_agent/users/u_123/sessions/s_123 -H "Content-Type: application/json" -d '{"key1": "value1", "key2": 42}'

Cloud Run とは何かを尋ね、エージェントの回答のみを表示するようにレスポンスをフィルタする

curl -X POST $AGENT_URL/run \
-H "Content-Type: application/json" \
-d "{
   \"appName\": \"my_agent\",
   \"userId\": \"u_123\",
   \"sessionId\": \"s_123\",
   \"newMessage\": { 
        \"role\": \"user\", 
        \"parts\": [{ \"text\": \"What is Cloud Run?\" 
    }]}
}" | python3 -c "import sys, json; print(json.load(sys.stdin)[-1]['content']['parts'][0]['text'])"

次のような出力が表示されます。

Hello! I am **demo_agent**, and I'm here to help you with your Cloud Run demo. **Cloud Run** is a fully managed compute platform by Google Cloud that allows you to run **containerized applications** in a serverless environment...

9. クリーンアップ

Google Cloud アカウントに継続的に課金されないようにするには、プロジェクト全体を削除するか(下記参照)、この Codelab で作成した個々のリソースを削除します。

nginx、color-app、private-backend、public-frontend サービスを削除する

gcloud run services delete nginx-service --region $REGION --quiet
gcloud run services delete color-app --region $REGION --quiet
gcloud run services delete private-backend --region $REGION --quiet
gcloud run services delete public-frontend --region $REGION --quiet

ADK エージェントを削除します(注: この例では us-west1 にデプロイされています)。

gcloud run services delete my-adk-agent-demo --region us-west1 --quiet

Secret Manager に保存されているシークレットを削除します。

gcloud secrets delete my-secret --quiet

Color App サービス アカウントを削除する

gcloud iam service-accounts delete color-app-sa@${PROJECT_ID}.iam.gserviceaccount.com --quiet

ADK エージェント サービス アカウントを削除する

gcloud iam service-accounts delete agent-sa@${PROJECT_ID}.iam.gserviceaccount.com --quiet

(省略可)プロジェクトを削除する

この Codelab 専用に新しいプロジェクトを作成した場合は、プロジェクト全体を削除して、すべてのリソースを一度に削除できます。

# run only if you want to delete the entire project
gcloud projects delete $PROJECT_ID

10. 完了

Codelab を完了しました。Cloud Run の基本を学びました。

学習した内容

  • nginx イメージをデプロイする
  • ソースコードからデプロイする
  • デプロイをロールバックする
  • デプロイをプレビューする
  • Developer Knowledge MCP サーバーツールを使用する
  • Cloud Run で Secret Manager を使用する
  • VPC 内の内部 Cloud Run サービスに接続する
  • ADK エージェントを Cloud Run にデプロイする