はじめに:環境変数が消える「あの現象」にサヨナラしよう
GCP Cloud Runを利用してアプリケーションを運用している際、こんな冷や汗をかく経験をしたことはありませんか?
「CI/CDパイプライン(GitHub ActionsやCloud Build)経由で新しいバージョンをデプロイしたら、コンソールで設定していた環境変数が全部消えてアプリが落ちた」
特に、microCMSのWebhook SecretやAPIキーなど、重要な機密情報を扱っている時にこれが起きると致命的です。コンソール画面から手動で設定し直せば一時的には直りますが、次のデプロイでまた消える……。これでは安心してリリースできません。
この記事では、この「デプロイによる環境変数消失問題」を、Google Secret Managerを導入することで根本的に解決し、セキュアで堅牢なデプロイフローを構築する方法を解説します。
なぜ環境変数は消えてしまうのか?
原因は、デプロイコマンド(gcloud run deploy 等)の挙動にあります。 CI/CDツール側で環境変数を明示的に指定せずにデプロイを行うと、ツール側の設定で上書きされたり、あるいは「空の状態」として更新されたりすることがあります。
cloudbuild.yaml に --update-env-vars を追加したり、GitHub ActionsのSecretsから流し込む方法もありますが、これらは設定ファイルのメンテナンスコストを高め、セキュリティリスク(Git上に設定が見えてしまう等)も伴います。
解決の鍵は「Google Secret Manager」への移行
最も推奨される解決策は、環境変数の管理場所(Source of Truth)をCloud Runの設定画面やCIツールではなく、Google Secret Managerに移すことです。
目指す最終構成
今回の移行で実現する構成は以下の通りです。
- Secret Manager: 環境変数の「真実」を一元管理。
- cloudbuild.yaml: デプロイ時にSecret Managerから値を参照するよう指示。
- Cloud Run: デプロイ時、Secret Managerから値をマウントして起動。
これにより、デプロイのたびに値を指定する必要がなくなり、かつ機密情報は安全に管理されます。
【実践】Secret Manager連携への完全移行ステップ
それでは、実際に移行作業を行っていきましょう。
Step 1: Secret Managerへのシークレット登録
まず、Google Cloud Consoleの「セキュリティ」>「Secret Manager」へ移動し、必要な環境変数をシークレットとして作成します。
例として、MICROCMS_WEBHOOK_SECRET を登録する場合:
- 「シークレットを作成」をクリック
- 名前:
MICROCMS_WEBHOOK_SECRET - シークレットの値: (実際の値を入力)
- 作成ボタンをクリック
これを必要な環境変数の分だけ繰り返します。
Step 2: サービスアカウントへの権限付与
ここが最大のハマりポイントです。Cloud Runを実行するサービスアカウントが、Secret Managerの値を読み取れるように権限を付与する必要があります。
IAM管理画面で、Cloud Runのサービスアカウント(通常は Compute Engine default service account または独自作成したもの)に対し、以下のロールを付与してください。
- Secret Manager のシークレット アクセサ (
roles/secretmanager.secretAccessor)
これがないと、Cloud Run起動時に「コンテナが起動できませんでした(シークレットが読めない)」というエラーになります。
Step 3: cloudbuild.yaml の書き換え
次に、デプロイ設定ファイルである cloudbuild.yaml を修正します。従来の --update-env-vars や --set-env-vars は廃止し、--update-secrets を使用します。
ポイントは --update-secrets の構文です。 環境変数名=シークレット名:バージョン という形式で指定します(バージョンは通常 latest でOK)。
移行時に遭遇したエラーと対処法(トラブルシューティング)
私たちが実際に移行を行った際に直面したエラーとその解決策を共有します。
問題1: Cloud Buildのsubstitutionエラー
複雑な処理を cloudbuild.yaml 内に直接書こうとした際、以下のエラーが発生しました。 invalid value for 'build.substitutions': key in the template "SERVICE_NAME"
解決策: 複雑なロジック(例:既存の環境変数を自動でSecret Managerに移す処理など)はYAML内に書かず、シェルスクリプト(scripts/migrate-secrets.sh 等)に切り出しました。YAMLからはそのスクリプトを呼び出すだけにすることで、構文エラーを回避できます。
問題2: Cloud Buildのサービスアカウント権限不足
デプロイ実行時に Permission 'run.services.get' denied というエラーが出ました。
解決策: Cloud Buildを実行しているサービスアカウント自体にも、Cloud Runを操作する十分な権限が必要です。以下のロールが付与されているか再確認しましょう。
- Cloud Run 管理者 (
roles/run.admin) - サービス アカウント ユーザー (
roles/iam.serviceAccountUser)
問題3: 新しいリビジョンにトラフィックが割り当てられない
デプロイは成功しているのに、ブラウザで見ると古いバージョンのまま……という現象です。
解決策: Cloud Runのデプロイコマンドによっては、デフォルトでトラフィックが新しいリビジョンに向かない場合があります。 前述の cloudbuild.yaml の例のように、明示的に以下のコマンドを実行するステップを追加しました。
まとめ:堅牢なインフラで開発に集中しよう
今回の移行により、以下のメリットが得られました。
- 環境変数が消えない: Secret Managerが一元管理するため、デプロイごとの事故がなくなりました。
- セキュリティ向上: Gitリポジトリから機密情報を完全に排除できました。
- 構成のシンプル化:
cloudbuild.yamlが「真実の源」として機能しやすくなりました。
環境変数の管理は地味ですが、システムの安定稼働には不可欠な要素です。「デプロイしたら動かなくなった!」と焦る前に、ぜひSecret Managerへの移行を検討してみてください。

