Next.js+BunをCloud Runに自動デプロイする方法

開発・プログラミングフロントエンド
author icon
能戸 成琉Software Engineer
Next.js+BunをCloud Runに自動デプロイする方法

こんにちは!エンジニアの能戸 成琉です。ご覧いただきありがとうございます!

この記事では、Next.jsとBunを使って高速な開発サイクルでCloud Run上にデプロイする手順について解説していきます。

Google Cloud上でサービスを管理したい方、Cloud Runを使ってデプロイプロセスを構築したい方は、ぜひ参考にしてみてください。

今回構築するシステムの技術構成

Next.js v15

  • この記事での役割: Webアプリケーションの本体
  • 特徴: 最新バージョンのReactフレームワークで、高速なビルドと開発体験が向上しており、サーバーサイドレンダリングやAPIルートを統合的に扱えます。

Bun(パッケージマネージャー)

  • この記事での役割: 依存関係管理とアプリケーション実行環境
  • 特徴: Node.jsの約3倍高速なパッケージインストール、TypeScriptネイティブサポート、組み込まれたバンドラー・テストランナー、JavaScriptCoreベースの高速実行エンジンを備えています。

Cloud Run

  • この記事での役割: アプリケーションのホスティング環境
  • 特徴: フルマネージドなコンテナ実行環境、自動スケーリング(0からN台まで)、リクエスト駆動の従量課金制、HTTPSエンドポイントの自動提供を行います。

Gthub Actions

  • この記事での役割: 自動デプロイパイプライン
  • 特徴: GitHubリポジトリとの統合、Workload Identity連携による安全な認証、並列実行によるビルド時間短縮、豊富なアクションエコシステムを活用できます。

GitHub ActionsでWorkload Identity連携しながらCloud Run上にNext.js、Bunをデプロイする手順について解説していきます。

Workload Identity連携って何?って方はこちらをご覧ください。

構成のメリットとユースケース

メリット

この技術構成の最大の利点は、開発プロセスの高速化です。Bunを使用することで、依存関係のインストールやビルドが従来のnpmやyarnより大幅に高速化され、開発中の待ち時間を削減できます。

セキュリティ面では、Workload Identity連携により、サービスアカウントキーの管理が不要になります。これまでサービスアカウントのキーファイルの取り扱いに注意を払っていた開発者にとって、運用負荷の軽減につながります。

コスト効率も優れており、Cloud Runの従量課金制により、トラフィックの少ない初期段階では低コストで運用できます。また、フルマネージドサービスの活用により、インフラ管理から解放され、アプリケーション開発に集中できる環境を構築できます。

ユースケース

この構成は、スタートアップでのMVP開発や個人開発に適しています。限られたリソースの中で迅速にプロダクトを市場投入する必要がある場合、高速なビルド・デプロイ環境が開発効率を大きく向上させます。

また、Google Cloud Platformの活用により安全性・信頼性を確保しつつ、将来的なスケールアップを見据えている場合にも有効な選択肢となります。

GitHub ActionsでCloud Runに自動デプロイする方法

GitHub ActionsとWorkload Identityを使って、コードをpushするだけでCloud Runに自動デプロイする環境を構築します。

Google Cloudの新規プロジェクトが作成済みであることを前提に進めていきます。

ステップ1: Google Cloudプロジェクトの各種設定

GitHub ActionsからGoogle Cloudにアクセスするための認証設定を行います。

サービスアカウントキーではなく、よりセキュアなWorkload Identityを使用します。

サービスアカウントの作成・設定

Google CloudコンソールのIAM管理からサービスアカウントの画面を開きます。

1. サービスアカウントの作成

新しいサービスアカウントを作成し、github-actions-dev のような分かりやすい名前を設定してください。

2. 権限の設定

Artifact Register 管理者」「Cloud Run 管理者」「Wokload Identity ユーザー」の3つをロールとして付与してください。

最小権限の原則に従い、必要最小限のロールのみを設定するように気をつけてください。

Workload Identityの作成・設定

IAM管理のWorkload Identity プール画面を開きます。この設定でGitHub ActionsからGoogle Cloudへの安全な認証が可能になります。

1. IDプールを作成する

まずIDプールを作成します。プール名は github-actions-pool-dev などの識別しやすい名前を設定してください。

2. プールにプロバイダを追加する

次にプロバイダを追加します。プロバイダタイプは「OpenID Connect (OIDC)」を選択し、発行者URLにhttps://token.actions.githubusercontent.com を設定します。

3. プロバイダの属性を構成する

プロバイダの属性構成ではマッピングを google.subject = assertion.repository に設定して、属性条件を assertion.repository_owner == "Githubアカウント名(組織名)” に設定してください。

4. サービスアカウントのアクセスを設定する

最後に、作成したサービスアカウントにアクセス権限を設定します。特定のGitHubリポジトリからのアクセスのみを許可するよう制限をかけることができます。

ステップ2: GitHub Actionsワークフローの作成と設定

Dockerfileの作成

プロジェクトルートにDockerfileを作成します。以下はNode.jsアプリケーションの例です:

# ベースイメージとしてbunを使用 
FROM oven/bun:1 AS base 
WORKDIR /app 

# 依存関係のインストール 
FROM base AS deps 
COPY package.json bun.lockb* ./ 
RUN bun install --frozen-lockfile 

# ビルドステージ 
FROM base AS builder 
WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . 

# Next.jsアプリケーションをビルド 
ENV NEXT_TELEMETRY_DISABLED=1 
ENV NODE_ENV=production 
RUN bun run build 

# 本番環境用のステージ - より軽量なイメージを使用 
FROM oven/bun:1-slim AS runner 
WORKDIR /app 
ENV NODE_ENV=production 
ENV NEXT_TELEMETRY_DISABLED=1 

# ビルド成果物をコピー 
COPY --from=builder /app/public ./public 
COPY --from=builder /app/.next/standalone ./ 
COPY --from=builder /app/.next/static ./.next/static 

# Cloud Runのデフォルトポート 
EXPOSE 8080 
ENV PORT=8080 

# bunでNext.jsサーバーを起動 
CMD ["bun", "server.js"]

WorkflowのYMLファイル作成

.github/workflows/deploy.yml ファイルを作成します:

name: Deploy to Production 
# mainブランチへのpush時に自動実行 
 on: 
  push: 
   branches: - main 

# 環境変数の一元管理 
# secrets経由で機密情報を安全に管理 
env: 
 PROJECT_ID: xxxxx 
 REGION: asia-northeast1 
 SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }} 
 WIF_PROVIDER: ${{ secrets.WIF_PROVIDER }} 
 DOCKER_REPOSITORY: xxxxx 
 SERVICE_NAME: xxxxx jobs: 

deploy: 
 runs-on: ubuntu-latest 

 # Google Cloud認証に必要な最小限の権限 
 # セキュリティのベストプラクティスに従い限定 
 permissions: 
  contents: "read" 
  id-token: "write" 

 steps: 
  # ソースコードをワークスペースに取得 
  # リポジトリ全体をチェックアウト
  - name: Checkout code 
    uses: actions/checkout@v4 

  # Workload Identity Federationで安全に認証 
  # サービスアカウントキーを保存せずキーレス認証 
  - name: Authenticate to Google Cloud 
    uses: google-github-actions/auth@v2 
    with: 
        workload_identity_provider: ${{ env.WIF_PROVIDER }}    
      service_account: ${{ env.SERVICE_ACCOUNT }} 

  # gcloudコマンドを使用可能にする 
  # 後続ステップでGoogle Cloud操作を実行 
  - name: Setup Cloud SDK 
    uses: google-github-actions/setup-gcloud@v2 
  
  # コミットハッシュを使ってユニークなイメージ名を生成 
  # 各デプロイを一意に識別し、ロールバックを容易にする 
  - name: Set Docker image name and tag 
    run: | echo "IMAGE_NAME=${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.DOCKER_REPOSITORY }}/${{ env.SERVICE_NAME }}:$(git rev-parse --short HEAD)" >> $GITHUB_ENV 

  # Artifact Registryリポジトリの準備 
  # 存在チェック後、必要時のみ新規作成で初回実行に対応 
  - name: Create Artifact Registry repository if not exists     
   run: | 
         gcloud artifacts repositories describe ${{ env.DOCKER_REPOSITORY }} \ --location=${{ env.REGION }} \ --project=${{ env.PROJECT_ID }} 2>/dev/null || \ 
      gcloud artifacts repositories create ${{ env.DOCKER_REPOSITORY }} \ --repository-format=docker \ --location=${{ env.REGION }} \ --project=${{ env.PROJECT_ID }} \ --description="Docker repository for Cloud Run deployment" 

  # Artifact Registry用のDocker認証を設定 
  # Dockerイメージをプッシュするための認証設定 
  - name: Configure Docker for Artifact Registry 
    run: | 
        gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet 

  # Dockerイメージをビルドしてレジストリにプッシュ 
  # アプリケーションをコンテナ化してGoogle Cloudに保存 
  - name: Build and push Docker image 
    run: | 
        docker build -t ${{ env.IMAGE_NAME }} . docker push ${{ env.IMAGE_NAME }} 

  # Cloud Runに新しいイメージをデプロイ 
  # リソース設定やセキュリティ設定も同時に適用 
  - name: Deploy to Cloud Run 
    run: | gcloud run deploy ${{ env.SERVICE_NAME }} \ 
            --region=${{ env.REGION }} \ 
            --image=${{ env.IMAGE_NAME }} \ 
            --platform=managed \ 
            --allow-unauthenticated \ 
            --port=3000 \ 
            --service-account=${{ env.SERVICE_ACCOUNT }} \ 
            --memory=1Gi \ 
            --cpu=2 \ 
            --max-instances=10 \ 
            --min-instances=0 \ 
            --project=${{ env.PROJECT_ID }}

環境変数とシークレットの設定

GitHubリポジトリの「Settings > Secrets and variables > Actions」で以下を設定:

SERVICE_ACCOUNT: github-actions-dev@bun-cloud-run.iam.gserviceaccount.com

WIF_PROVIDER: projects/<プロジェクト番号>/locations/global/workloadIdentityPools/github-actions-pool-dev/providers/github

全ての設定が完了しました🚀

mainにpushしてCloud Runの確認してみましょう!

無事にデプロイされてることが確認できました!

Cloud Buildの継続的デプロイとの違い

今回のケースでは、GitHub Actions + Workload Identityを使ってビルド・デプロイプロセスを構築しましたが、Cloud Buildを使用してもCloud Run上にデプロイすることは可能です。

Cloud BuildはGoogle Cloud内部で実行されるため、ストレージやDB管理など全てGoogle Cloudで管理している場合に適しています。パフォーマンス面でも内部完結型なので高速でキーレスで動作します。

ただし、柔軟性の面では劣る部分があり、複雑な条件分岐やマトリックスビルドが困難で、利用できるツールやプラグインも限定的です。また、マルチクラウド対応が複雑になるため、ベンダーロックインのリスクも考慮する必要があります。

一方、GitHub Actions + Workload Identityは初期設定が複雑ですが、複数環境への段階的デプロイや手動承認プロセス、充実した自動テストやセキュリティスキャンが可能です。特にオープンソースプロジェクトでは無料で利用でき、チームが成長して要件が複雑になった際の拡張性も優れています。

シンプルなプロジェクトでGoogle Cloud中心のアーキテクチャならCloud Build、複雑な要件や将来的な拡張性を重視するならGitHub Actions + Workload Identityを選択するのが適切です。

おわり

最後までお読みいただき、ありがとうございました。

この記事では、Next.js+BunをCloud RunにGithub Actionsで自動デプロイする方法・手順について解説しました。

この記事が参考になった/良かったと思っていただけたら、以下のボタンからシェアしていただけると嬉しいです。筆者の励みになり、今後の改善にもつながりますので、よろしくお願いします🚀

📩 お仕事に関するお問い合わせ

長期的な運用を見据えた開発、スピーディな実装、安全性の確保、そして開発者の継続的なスキルアップ向上を大切にして、プロジェクトをサポートいたします。

これまでに携わってきた多くのプロジェクトで培った経験とナレッジを活かし、技術的な課題解決から運用改善まで、幅広い開発支援を行います。一人ひとりのニーズに合わせて、丁寧に支援させていただきます。

ご相談やお問い合わせは、こちらからお気軽にご連絡ください。

👤 記事を書いた人

能戸 成琉のアイコン

能戸 成琉

Software Engineer

スタートアップでフルスタックエンジニアをしながら、フリーランスとしてWebアプリケーションの開発・運用支援や技術記事の執筆を行っております。