[SAMPLE] Vercelでゼロダウンタイムデプロイを実現する方法
Vercelでゼロダウンタイムデプロイを実現する方法
Vercelは、Next.jsアプリケーションのホスティングに最適化されたプラットフォームです。本記事では、Vercelの機能を最大限活用し、ユーザーに影響を与えないゼロダウンタイムデプロイを実現する方法を詳しく解説します。
Vercelのデプロイメカニズム
Atomic Deploymentsの仕組み
VercelはAtomic Deploymentsを採用しており、新しいバージョンが完全にデプロイされるまで、古いバージョンへのトラフィックを維持します。
デプロイの流れ:
- コードを
プッシュ
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からの即座のロールバック
- Vercel Dashboardにアクセス
- Deploymentsタブを開く
- 以前の安定バージョンを選択
- 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 | 用途 |
|---|---|---|---|
| Production | main | example.com | 本番環境 |
| Staging | develop | staging.example.com | ステージング |
| Preview | feature/* | 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 --followEdge 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
0
投稿0
フォロワー0
いいねプロパティ
ページ
ビジネスChatGPTPython
ジェフ・ベゾスまつもとゆきひろ
コメント