- Published on
個人開発を楽にする:Cloud Run自動デプロイ
- Authors
- Name
- Nomad Dev Life

夜中にポチポチしない。PRマージで実現するCloud Run自動デプロイ
個人で開発をしていると、コードを書いた後のデプロイ作業が思いのほか手間になることがあります。
特に私の場合、Julesで進める、ルーズな個人開発ライフ | Nomad Dev Lifeで書いたように、 夜にマージしています。いくらCloud Runを利用しているとはいえ、一日の終わりにWebアプリケーションのフロントエンドとバックエンドのサービスをそれぞれ手動でデプロイするのは少々面倒です。
そこで今回は、GitHubのプルリクエストをマージしたら自動的にCloud Runへデプロイされる仕組みを構築します。
サービスアカウントの作成
まずはGCP側で、GitHub ActionsがCloud Runにデプロイできるようにするためのサービスアカウントを用意します。
僕が最初に悩んだのは、このサービスアカウントにどのロールを付与すれば良いのかでした。結論から言うと、以下のロールを付ければ問題ありません。さらに厳密に設定することも可能なので、詳細についてはLLMに尋ねてみてください。
- Cloud Run Admin (roles/run.admin)
- Artifact Registry Writer (roles/artifactregistry.writer)
- Service Account User (roles/iam.serviceAccountUser)
- Secret Manager Secret Accessor (roles/secretmanager.secretAccessor)
- Cloud RunがSecretにアクセスする場合のみ必要
作成手順は以下の通りです:
- GCP コンソールで「IAMと管理」→「サービスアカウント」を開く
- 新しいサービスアカウントを作成(例: github-actions-deployer)
- 上記 3 つのロールを付与する
- JSON キーを作成し、ダウンロードしておく
このJSONファイルをGitHubのSecretsに登録します。今回はGOOGLE_CREDENTIALS
という名前にしています。
Artifact Registry にリポジトリを作る
次に、ビルドしたコンテナを保存しておくArtifact Registryを用意します。フロント/バックエンドそれぞれに1つ作成しました。
コマンドはこんな感じで作成できます:
gcloud artifacts repositories create my-repo \
--repository-format=docker \
--location=asia-northeast1 \
--description="My app container registry"
Artifact RegistryとCloud RunのRegionはasia-northeast1
にしています。お好みで変更してください。
my-repo
は、Githubのプロジェクト名と合わせておくと良いでしょう。以降の説明は、それを前提としています。
Github Actionsでコンテナを作成し、Artifact Registryにpushする
GCPにはArtifact Registryという成果物を管理するリポジトリがあります。 コンテナイメージを作成してそこにpushしておくと、Cloud Runでデプロイする際にそのコンテナイメージを指定することができます。
Github Actionsのワークフローの設定ファイル(.github/workflows/xxx.yml)に、コンテナを作成してArtifact Registryにpushするまでのワークフローを記載します。
on:
push:
branches:
- main
env:
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
IMAGE: asia-northeast1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ github.event.repository.name }}/${{ github.sha }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run tests and collect coverage
run: yarn test --coverage
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }}
- name: Configure Google Cloud SDK
run: |
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
gcloud config set project $GCP_PROJECT_ID
- name: Build and Push Docker Image
run: |
docker build --platform linux/amd64 -t $IMAGE .
docker push $IMAGE
まず、mainブランチにpush/mergeされた時に動作するように、on
を記載し、main
ブランチを指定します。
secrets.GCP_PROJECT_ID
は、文字通りGCPのプロジェクトIDです。これもGithubのSecretとして登録しておきます。 GCPのプロジェクトIDは、Google Cloudコンソールの画面上部のナビゲーションバーにあるプロジェクト名が表示されている部分をクリックすると表示されます。
build
ジョブでビルドし、deploy
ジョブでコンテナイメージを作成してArtifact Registryにpushしています。
GitHub ActionsでCloud Runに自動デプロイ
今回、Cloud Runへのdeployは、フロント/バックエンドともに一度はできている状態から始めます。必要な環境変数やSecrets、その他のCloud Runの設定は、すでに済んでいる状態です。 その状態から、Github ActionsでCloud Runに自動デプロイします。
Cloud Runへのdeployは、先程のワークフローのdeploy
ジョブに以下を追加します。
- name: Deploy to Cloud Run
run: |
gcloud run deploy (Cloud Runのサービス名) \
--image $IMAGE \
--region asia-northeast1 \
--platform managed \
--allow-unauthenticated
ここまでで、mainブランチにpush/mergeされると、Github Actionsが開始され、最新のコンテナイメージがCloud Runにデプロイされます。
Discord に通知を送る
デプロイが終わったら、Discordに通知を送るようにしました。やっぱり「お、デプロイ通ったな」というのがすぐ分かると気分が良いんですよね。
DiscordにはWebhook URLが用意されているので、GitHub Actionsからcurl
で簡単に叩けます。
Discord Webhook URLを作る:
- Discord サーバーで通知したいチャンネルを選ぶ
- 右上「チャンネル編集」 → 統合 (Integrations)
- Webhook を作成 → 名前を付けて、Webhook URL をコピー
- その URL を GitHub Secrets に保存(例:
GCP_CI_CD_DISCORD_WEBHOOK
)
あとはGithub ActionsのワークフローにDiscordへのメッセージ送信を組み込みます。 こちらも、先程のワークフローのdeploy
ジョブに以下を追加します。
- name: Notify Discord
if: success()
run: |
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"✅ The deployment to Cloud Run is complete!\nService: (サービス名)\nCommit: $GITHUB_SHA\"}" \
${{ secrets.GCP_CI_CD_DISCORD_WEBHOOK }}
- name: Notify Discord (on failure)
if: failure()
run: |
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"❌ The deployment failed\nService: (サービス名)\nCommit: $GITHUB_SHA\"}" \
${{ secrets.GCP_CI_CD_DISCORD_WEBHOOK }}
これで、Cloud Runへのデプロイが完了した後に、Discordにメッセージが届くようになります。
おわりに
この仕組みを導入してからは、手動でデプロイする必要がなくなり、PRをマージする=リリースという自然な流れができました。
小さな変更を頻繁にリリースすることも苦にならなくなり、結果として個人開発のサイクルが一気に回しやすくなったと感じています。