最近 AI Studio の build タブに加わった Cloud Run へのワンクリックデプロイを、社内ツール程度のつもりで作った Gemini アプリに試したときのことです。数分待つだけで公開 URL が発行され、ブラウザから動くものが確認できました。正直、ここまでの体験は見事だと感じました。ただ、そのまま URL を人に共有しようとして手が止まりました。個人開発で複数のサービスを Cloud Run に載せてきた経験から言うと、「動く URL がある」と「公開してよい状態にある」の間には、それなりの距離があるからです。
デプロイされたサービスの設定を gcloud run services describe で眺めてみると、案の定というべきか、点検したい箇所がいくつも見つかりました。API キーはどこに置かれているのか。URL は誰でも叩けるのか。インスタンスはどこまでスケールし、費用の天井はあるのか。この構成を今後どうやって更新していくのか。どれもプロトタイプの段階では気にしなくてよかったことばかりで、公開した瞬間から全部が自分の問題になります。
そこで、ワンクリックデプロイの直後に私自身が実際に行った点検を、再現できる手順として整理しておくことにしました。生成 AI が書いたコードを捨てて作り直すのではなく、活かしたまま運用レベルへ引き上げる、という方針の記録です。
ワンクリックデプロイが済ませてくれること・くれないこと
まず境界をはっきりさせておきます。ワンクリックデプロイが肩代わりしてくれるのは、おおよそ次の範囲です。
コンテナのビルドと Cloud Run サービスの作成
公開 URL の発行と HTTPS の終端
Gemini API を呼ぶための資格情報の受け渡し(動く状態にすること)
一方で、次の判断は誰も肩代わりしてくれません。
その URL を 誰に 叩かせるか(認証・認可)
API キーやシークレットを どこで 管理し続けるか
トラフィックが想定を超えたとき いくらまで 払うか
生成されたコードを どう更新し続ける か
プロトタイプと本番の差は機能ではなく、この4つの答えを持っているかどうかです。以降、順番に埋めていきます。
点検 1: API キーの居場所を確認する
最初に見るべきはここです。デプロイ直後の構成では、Gemini API キーが環境変数としてサービスに直接設定されていることがあります。環境変数は gcloud run services describe やコンソールを見られる人全員に露出しますし、リビジョンの設定としてコピーされ続けます。
2026 年 6 月 19 日以降、制限のない API キーからのリクエストは Gemini API 側で拒否されるようになりました。キーに制限を付けるのは当然の前提として、私はさらに一歩進めて、キー本体を Secret Manager に移すところまでを「公開前の最低ライン」にしています。
# 1. シークレットを作成してキーを格納する
printf '%s' "YOUR_GEMINI_API_KEY" | \
gcloud secrets create gemini-api-key --data-file=-
# 2. Cloud Run のサービスアカウントに読み取り権限を付ける
gcloud secrets add-iam-policy-binding gemini-api-key \
--member= "serviceAccount:my-service-sa@my-project.iam.gserviceaccount.com" \
--role= "roles/secretmanager.secretAccessor"
# 3. 環境変数の直置きをやめ、シークレット参照に切り替える
gcloud run services update my-genai-app \
--region=asia-northeast1 \
--remove-env-vars=GEMINI_API_KEY \
--set-secrets=GEMINI_API_KEY=gemini-api-key:latest
3 のコマンドが成功すると、アプリケーションコードからは今までどおり GEMINI_API_KEY 環境変数として見えるため、生成されたコードを 1 行も書き換えずに 保管場所だけを差し替えられます。ここがこの手順の気に入っているところで、プロトタイプのコードに手を入れる前に安全性だけ先に上げられます。
あわせて、デフォルトの Compute Engine サービスアカウントで動いている場合は、専用のサービスアカウントを作って付け替えることを推奨します。デフォルトのままだと、プロジェクト内の他リソースへ広い権限を持ったまま公開サービスが動くことになります。
gcloud iam service-accounts create my-service-sa \
--display-name= "genai app runtime"
gcloud run services update my-genai-app \
--region=asia-northeast1 \
--service-account=my-service-sa@my-project.iam.gserviceaccount.com
点検 2: その URL、誰でも叩ける状態になっていないか
ワンクリックデプロイの目的は「すぐ試せる URL を出すこと」なので、サービスは未認証アクセスを許可した状態で公開されているはずです。試作の共有ならそれでよくても、Gemini API の呼び出しはリクエストのたびに費用が発生します。つまり 未認証の公開 URL は、他人があなたの財布でトークンを消費できる窓口 でもあります。
利用者が自分と数人のうちは、Cloud Run の IAM 認証に切り替えるのが最短です。
# 未認証アクセスを閉じる
gcloud run services update my-genai-app \
--region=asia-northeast1 \
--no-allow-unauthenticated
# 叩いてよい人にだけ起動権限を付与する
gcloud run services add-iam-policy-binding my-genai-app \
--region=asia-northeast1 \
--member= "user:teammate@example.com" \
--role= "roles/run.invoker"
呼び出す側は ID トークンをヘッダーに付けます。curl での動作確認はこの形です。
curl -H "Authorization: Bearer $( gcloud auth print-identity-token)" \
https://my-genai-app-xxxxxxxx-an.a.run.app/api/generate
不特定多数に公開するアプリなら IAM では守れないので、アプリ側の認証(Firebase Authentication など)とレート制限を実装してから開けることになります。ここは用途によって答えが変わる部分ですが、「認証なしで公開したまま気づいたら数週間経っていた」が一番避けたい状態です。まず閉じてから、開け方を考える順番が安全です。
点検 3: 費用の天井を先に決める
Gemini アプリの費用は「Cloud Run の実行費」と「Gemini API のトークン費」の二階建てです。ここでの落とし穴は、Cloud Run 側の上限だけ絞って安心してしまうことです。放置したときに伸びるのは後者のトークン費なので、両方に天井を付けてはじめて事故を回避できます。
Cloud Run 側は、スケール上限と同時実行数を明示します。プロトタイプ相当の負荷なら、私は最初にかなり保守的な値を入れておき、必要になってから上げる運用にしています。
gcloud run services update my-genai-app \
--region=asia-northeast1 \
--max-instances=2 \
--concurrency=20
Gemini API 側は、プロジェクト単位で月額の上限を設定できる Project Spend Caps を入れておくと、キー漏洩や想定外のループのような事故でも被害額が確定します。上限に達すると止まるという性質そのものが保険になります。アプリ側でのソフト上限との二段構えについては、Project Spend Caps とアプリ側ソフト上限で、無人パイプラインの費用事故を二重に止める で詳しく書きました。
もうひとつ、コールドスタートは費用と体験のトレードオフとして把握しておくと判断が楽です。私の手元の Node 系コンテナでは、アイドル状態からの初回応答に 2〜4 秒程度かかります。これが気になる場合は --min-instances=1 で常駐させられますが、当然アイドル分の課金が発生します。試作を昇格させた直後の段階では、私は min-instances を入れず「最初の 1 リクエストは遅くてよい」と割り切ることが多いです。
点検 4: 生成されたコードの所有権を取り戻す
ワンクリックデプロイの状態は「AI Studio 上の成果物がクラウドに写っている」状態であって、自分のリポジトリと CI が起点になっていません。このままだと、次の変更をどこでやるのか、誰がいつデプロイしたのかが曖昧なままサービスが生き続けます。
やることは単純で、コードをエクスポートして自分のリポジトリに入れ、以後のデプロイをソース起点に切り替えるだけです。
# リポジトリ化したソースからのデプロイに載せ替える
gcloud run deploy my-genai-app \
--region=asia-northeast1 \
--source=. \
--no-allow-unauthenticated
同名サービスに対して gcloud run deploy を実行すれば新しいリビジョンとして載るので、URL や設定は引き継がれます。以後は GitHub Actions なりで main ブランチからこのコマンドを叩く形にすれば、ワンクリックデプロイは「最初の一回の足場」だった、という位置づけに整理できます。
ここで一度だけ、生成されたコードを読む時間を取ることをおすすめします。全部を理解する必要はありませんが、Gemini をどのモデル名で呼んでいるか と リトライやタイムアウトの有無 の 2 点だけは確認する価値があります。プレビュー版のモデル名が直書きされていれば、いずれ廃止で止まります。基盤側の変更で自動処理が静かに止まる問題への備えは、静かに止まる自動処理を防ぐ — Gemini 基盤変更に備える事前検証ゲートの設計 にまとめています。
点検 5: 観測 — 「動いているか」を数字で言えるようにする
最後は観測です。Cloud Run は標準出力の JSON を構造化ログとして拾ってくれるので、Gemini 呼び出しの結果とトークン量を 1 行で吐くだけでも、運用の解像度が大きく変わります。
import json, time
def log_generation (model: str , resp, started: float ) -> None :
"""Gemini 呼び出しごとに 1 行の構造化ログを出す。
Cloud Logging 側で jsonPayload として検索・集計できる。"""
usage = resp.usage_metadata
print (json.dumps({
"severity" : "INFO" ,
"message" : "gemini_generation" ,
"model" : model,
"input_tokens" : usage.prompt_token_count,
"output_tokens" : usage.candidates_token_count,
"latency_ms" : int ((time.time() - started) * 1000 ),
}))
期待する出力はこのような 1 行です。
{ "severity" : "INFO" , "message" : "gemini_generation" , "model" : "gemini-flash-latest" , "input_tokens" : 412 , "output_tokens" : 380 , "latency_ms" : 2150 }
このログがあると、「今月のトークン消費が先月比でどう動いたか」「レイテンシが悪化したのはいつからか」に数字で答えられます。個人開発では専任の監視役がいないぶん、ログベースの指標とアラートポリシーを先に仕込んでおくのが、結局いちばん安上がりだと感じています。私自身の運用では「5 分間のエラー率が 5% を超えたら通知」「p95 レイテンシが 10 秒を超えたら通知」の 2 本だけを入れ、予算アラートは月 3,000 円の 50% と 90% で通知するように設定しています。
点検リストのまとめと、引き継ぐか書き直すかの基準
ここまでの点検を、初期状態との対比で一覧にしておきます。
点検項目 デプロイ直後の状態 引き上げ後の状態
API キー 環境変数に直置きの可能性 Secret Manager 参照+制限付きキー
サービスアカウント デフォルト SA の可能性 専用 SA・最小権限
アクセス制御 未認証で全公開 IAM 認証またはアプリ側認証+レート制限
費用 スケール上限・支出上限なし max-instances / concurrency / Spend Caps
デプロイ経路 AI Studio からの手動更新 リポジトリ起点の gcloud run deploy / CI
観測 デフォルトのリクエストログのみ トークン量・レイテンシの構造化ログ+アラート
なお、この引き上げ作業を進める中で「これは引き継がず書き直したほうが早い」と判断する場合もあります。私はこの判断を 2 つの基準で行っていて、リクエストの境界(入力の検証と出力の整形)が読み取れないコード と、特定のプレビュー機能に依存していて代替が見えないコード は書き直します。逆に、多少冗長でも境界が読めるコードなら、上の手順で運用に引き上げてから少しずつ直すほうが、結果的に速く安定します。フルスクラッチで Cloud Run 上の Gemini API サーバーを設計する場合の構成は、Gemini 3.1 Pro × Cloud Run:サーバーレスAI APIの本番構築 が参考になるはずです。
最初の 30 分でやる順番としては、次の 3 つをおすすめします。
gcloud run services describe で環境変数とアクセス設定を自分の目で確認する
API キーを Secret Manager 参照に差し替える(コードの変更は不要です)
公開が必要になるまで --no-allow-unauthenticated で受け口を閉じる
ここまで進めば、残りの点検は落ち着いて取り組めます。同じようにプロトタイプの公開判断で迷っている方の、出発点になれば嬉しいです。