Published on

個人開発を楽にする:Cloud Run自動デプロイ

Authors
  • avatar
    Name
    Nomad Dev Life
    Twitter
2025-10-04-title

夜中にポチポチしない。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にアクセスする場合のみ必要

作成手順は以下の通りです:

  1. GCP コンソールで「IAMと管理」→「サービスアカウント」を開く
  2. 新しいサービスアカウントを作成(例: github-actions-deployer)
  3. 上記 3 つのロールを付与する
  4. 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を作る:

  1. Discord サーバーで通知したいチャンネルを選ぶ
  2. 右上「チャンネル編集」 → 統合 (Integrations)
  3. Webhook を作成 → 名前を付けて、Webhook URL をコピー
  4. その 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をマージする=リリースという自然な流れができました。

小さな変更を頻繁にリリースすることも苦にならなくなり、結果として個人開発のサイクルが一気に回しやすくなったと感じています。