[SAMPLE] Vercelでゼロダウンタイムデプロイを実現する方法

2 か月前
12

Vercelでゼロダウンタイムデプロイを実現する方法

Vercelは、Next.jsアプリケーションのホスティングに最適化されたプラットフォームです。本記事では、Vercelの機能を最大限活用し、ユーザーに影響を与えないゼロダウンタイムデプロイを実現する方法を詳しく解説します。

Vercelのデプロイメカニズム

Atomic Deploymentsの仕組み

VercelはAtomic Deploymentsを採用しており、新しいバージョンが完全にデプロイされるまで、古いバージョンへのトラフィックを維持します。

デプロイの流れ:

  1. コードを

プッシュ
2. Vercelがビルドを開始
3. 新しいバージョンが完全にビルド完了
4. トラフィックを瞬時に新バージョンに切り替え
5. 古いバージョンは一定期間保持(ロールバック可能)

プレビューデプロイメントの活用

ブランチごとの自動プレビュー

{ "name": "my-next-app", "version": "1.0.0", "scripts": { "dev": "next dev", "build": "next build", "start": "next start" } }

vercel.json の設定:

{ "git": { "deploymentEnabled": { "main": true, "develop": true } }, "github": { "autoAlias": true, "autoJobCancelation": true, "silent": false } }

プレビューURLの命名規則

  • プロダクション: https://example.com
  • ブランチデプロイ: https://branch-name.vercel.app
  • コミットデプロイ: https://app-name-git-branch-team.vercel.app

環境変数の管理

プロダクションとプレビューで異なる環境変数

# Vercel CLI で環境変数を設定 vercel env add NEXT_PUBLIC_API_URL production vercel env add NEXT_PUBLIC_API_URL preview vercel env add DATABASE_URL production # 環境変数の確認 vercel env ls

.env.local と Vercel環境変数の使い分け

// lib/config.ts export const config = { apiUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001', databaseUrl: process.env.DATABASE_URL, isDevelopment: process.env.NODE_ENV === 'development', isProduction: process.env.VERCEL_ENV === 'production', isPreview: process.env.VERCEL_ENV === 'preview', }

カナリアデプロイメント

段階的なトラフィック移行

Vercelでは、トラフィックを段階的に新バージョンに移行できます。

{ "version": 2, "routes": [ { "src": "/(.*)", "dest": "/$1", "headers": { "x-deployment-version": "v2" }, "continue": true } ] }

A/Bテストの実装

// middleware.ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { // 10%のユーザーを新バージョンに振り分け const bucket = Math.random() const isNewVersion = bucket < 0.1 const response = NextResponse.next() if (isNewVersion) { response.cookies.set('version', 'v2') } return response }

ロールバック戦略

Vercel Dashboardからの即座のロールバック

  1. Vercel Dashboardにアクセス
  2. Deploymentsタブを開く
  3. 以前の安定バージョンを選択
  4. Promoteボタンをクリック

Vercel CLIでのロールバック

# デプロイ履歴の確認 vercel ls # 特定のデプロイをプロダクションに昇格 vercel promote <deployment-url> # 直前のデプロイにロールバック vercel rollback

パフォーマンス最適化

Edge Functionsの活用

// pages/api/hello.ts import { NextRequest } from 'next/server' export const config = { runtime: 'edge', } export default async function handler(req: NextRequest) { return new Response( JSON.stringify({ message: 'Hello from Edge', region: process.env.VERCEL_REGION, }), { status: 200, headers: { 'content-type': 'application/json', }, } ) }

ISRの最適な設定

// pages/blog/[slug].tsx export async function getStaticProps({ params }) { const post = await getPost(params.slug) return { props: { post }, revalidate: 60, // 60秒ごとに再生成 } } export async function getStaticPaths() { const posts = await getAllPosts() return { paths: posts.map((post) => ({ params: { slug: post.slug }, })), fallback: 'blocking', // 新しいページはサーバーサイドで生成 } }

モニタリングとアラート

Vercel Analyticsの統合

// pages/_app.tsx import { Analytics } from '@vercel/analytics/react' export default function MyApp({ Component, pageProps }) { return ( <> <Component {...pageProps} /> <Analytics /> </> ) }

カスタムメトリクスの送信

import { sendMetric } from '@vercel/analytics' export async function trackCheckout(amount: number) { await sendMetric({ name: 'checkout', value: amount, tags: ['ecommerce'], }) }

セキュリティ設定

vercel.json でのセキュリティヘッダー

{ "headers": [ { "source": "/(.*)", "headers": [ { "key": "X-Content-Type-Options", "value": "nosniff" }, { "key": "X-Frame-Options", "value": "DENY" }, { "key": "X-XSS-Protection", "value": "1; mode=block" }, { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" }, { "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" } ] } ] }

環境変数の暗号化

# Vercel CLIで環境変数を暗号化して保存 vercel env add SECRET_KEY production --sensitive # GitHubシークレットと連携 vercel env pull .env.local

デプロイフックの活用

Webhookによる外部システムとの連携

// pages/api/deploy-hook.ts import type { NextApiRequest, NextApiResponse } from 'next' export default async function handler( req: NextApiRequest, res: NextApiResponse ) { // Vercelのデプロイフックを検証 const secret = req.headers['x-vercel-signature'] if (secret !== process.env.DEPLOY_HOOK_SECRET) { return res.status(401).json({ error: 'Unauthorized' }) } // CMSの更新時に再デプロイをトリガー await fetch(process.env.VERCEL_DEPLOY_HOOK_URL!, { method: 'POST', }) res.status(200).json({ message: 'Deployment triggered' }) }

Zapierとの統合

# Vercel Deploy Hookを作成 curl -X POST https://api.vercel.com/v1/integrations/deploy-hooks \ -H "Authorization: Bearer <TOKEN>" \ -H "Content-Type: application/json" \ -d '{ "name": "Content Update Hook", "ref": "main" }'

チーム開発のベストプラクティス

環境の分離

環境ブランチURL用途
Productionmainexample.com本番環境
Stagingdevelopstaging.example.comステージング
Previewfeature/*feature-name.vercel.app機能開発

vercel.json でのルーティング設定

{ "rewrites": [ { "source": "/api/:path*", "destination": "https://api.example.com/:path*" }, { "source": "/blog/:slug", "destination": "/blog/[slug]" } ], "redirects": [ { "source": "/old-page", "destination": "/new-page", "permanent": true } ] }

コスト最適化

使用量の監視

# 現在の使用量を確認 vercel billing # 実行時間の確認 vercel logs --follow

Edge Functionsの適切な利用

推奨される使い方:

  • 認証チェック
  • リダイレクト
  • ヘッダーの追加
  • 軽量なデータ変換

避けるべき使い方:

  • 重い計算処理
  • 大量のデータ処理
  • 長時間実行される処理

トラブルシューティング

デプロイエラーの確認

# デプロイログの確認 vercel logs <deployment-url> # ビルドログの詳細表示 vercel build --debug

よくあるエラーと対処法

1. ビルドタイムアウト

{ "builds": [ { "src": "package.json", "use": "@vercel/next", "config": { "maxDuration": 60 } } ] }

2. メモリ不足

// next.config.js module.exports = { experimental: { // ビルド時のメモリ使用量を削減 workerThreads: false, cpus: 1, }, }

まとめ

Vercelでゼロダウンタイムデプロイを実現するポイント:

  • Atomic Deploymentsの活用: 瞬時の切り替え
  • プレビューデプロイ: 本番前の検証
  • 段階的ロールアウト: リスクの低減
  • 即座のロールバック: 問題発生時の迅速な対応
  • 適切なモニタリング: 問題の早期発見

これらの機能を組み合わせることで、安全で高速なデプロイメントプロセスを構築できます。

コメント

0
0
0