Version 1.0.0 | プロジェクト: PropCloud - 賃貸管理クラウド
PropCloud のローカル開発環境セットアップから AWS 本番環境へのデプロイまでを解説します。
| ソフトウェア | バージョン | 用途 |
|---|---|---|
| Node.js | 22 以上 | アプリケーションランタイム |
| Docker / Docker Compose | 最新版 | PostgreSQL・Redis の起動 |
| Git | 最新版 | ソースコード管理 |
# 1. リポジトリをクローン git clone https://github.com/gmaeshima-blip/real_estate.git cd real_estate # 2. Docker で依存サービスを起動 docker compose up -d # 3. 依存パッケージのインストール npm install # 4. 環境変数ファイルの作成 cp .env.example .env.local # 5. Prisma クライアント生成 & スキーマ反映 npx prisma generate npx prisma db push # 6. シードデータの投入(任意) npm run db:seed # 7. 開発サーバーの起動 npm run dev
http://localhost:3000 でアプリケーションにアクセスできます。
# Prisma Studio(DB GUI)を起動 npm run db:studio # マイグレーション作成・実行 npm run db:migrate # テスト実行 npm run test # カバレッジ計測 npm run test:coverage # リント npm run lint # コード整形 npm run format
開発用の `docker-compose.yml` は以下のサービスを提供します。
| サービス | イメージ | ポート | 用途 |
|---|---|---|---|
| `postgres` | postgres:16-alpine | 5432 | メインデータベース |
| `redis` | redis:7-alpine | 6379 | セッションキャッシュ・ジョブキュー |
version: "3.8"
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: propcloud
POSTGRES_PASSWORD: propcloud_dev
POSTGRES_DB: propcloud_dev
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U propcloud"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
redis_data:`.env.example` に定義される環境変数の一覧です。
| 変数名 | 説明 | 例 |
|---|---|---|
| `DATABASE_URL` | PostgreSQL 接続文字列 | `postgresql://propcloud:propcloud_dev@localhost:5432/propcloud_dev` |
| 変数名 | 説明 | 例 |
|---|---|---|
| `REDIS_URL` | Redis 接続文字列 | `redis://localhost:6379` |
| 変数名 | 説明 | 例 |
|---|---|---|
| `JWT_SECRET` | JWT 署名用シークレットキー | `your-secret-key-min-32-chars` |
| `JWT_EXPIRATION` | JWT トークン有効期間 | `24h` |
| 変数名 | 説明 | 例 |
|---|---|---|
| `NEXT_PUBLIC_APP_URL` | アプリケーションの公開 URL | `http://localhost:3000` |
| `NEXT_PUBLIC_APP_NAME` | アプリケーション表示名 | `PropCloud` |
| `NODE_ENV` | 実行環境 | `development` / `production` |
| 変数名 | 説明 | 例 |
|---|---|---|
| `STORAGE_TYPE` | ストレージ種別 | `local` / `s3` |
| `AWS_S3_BUCKET` | S3 バケット名 | `propcloud-documents-prod` |
| `AWS_S3_REGION` | S3 リージョン | `ap-northeast-1` |
| `AWS_ACCESS_KEY_ID` | AWS アクセスキー | - |
| `AWS_SECRET_ACCESS_KEY` | AWS シークレットキー | - |
| 変数名 | 説明 | 例 |
|---|---|---|
| `SMTP_HOST` | SMTP サーバーホスト | `smtp.ses.ap-northeast-1.amazonaws.com` |
| `SMTP_PORT` | SMTP ポート | `587` |
| `SMTP_USER` | SMTP ユーザー名 | - |
| `SMTP_PASSWORD` | SMTP パスワード | - |
| `EMAIL_FROM` | 送信元メールアドレス | `noreply@propcloud.jp` |
| 変数名 | 説明 | 例 |
|---|---|---|
| `SENTRY_DSN` | Sentry DSN | `https://xxx@sentry.io/xxx` |
| `LOG_LEVEL` | ログレベル | `info` / `debug` / `warn` / `error` |
本番環境は AWS 上に以下の構成でデプロイされます。
┌──────────────────┐
│ Route 53 │
│ (DNS) │
└────────┬─────────┘
│
┌────────▼─────────┐
│ CloudFront │
│ (CDN) │
└────────┬─────────┘
│
┌────────▼─────────┐
│ ALB │
│ (ロードバランサー) │
└────────┬─────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌────────▼───┐ ┌───────▼────┐ ┌───────▼────┐
│ ECS Task │ │ ECS Task │ │ ECS Task │
│ (Fargate) │ │ (Fargate) │ │ (Fargate) │
└────────┬───┘ └───────┬────┘ └───────┬────┘
│ │ │
└──────────────┼──────────────┘
│
┌──────────────┼──────────────┐
│ │
┌────────▼─────────┐ ┌─────────▼────────┐
│ RDS │ │ ElastiCache │
│ (PostgreSQL 16) │ │ (Redis 7) │
│ Multi-AZ │ │ クラスターモード │
└──────────────────┘ └──────────────────┘| サービス | 用途 | 設定 |
|---|---|---|
| ECS Fargate | アプリケーション実行 | 最小2タスク、オートスケーリング(CPU 70%) |
| ECR | Docker イメージレジストリ | ライフサイクルポリシーで30世代保持 |
| RDS (PostgreSQL 16) | メインデータベース | Multi-AZ、db.r6g.large、自動バックアップ7日間 |
| ElastiCache (Redis 7) | キャッシュ・セッション | cache.r6g.large、クラスターモード |
| ALB | ロードバランサー | ヘルスチェック `/api/health`、HTTPS 終端 |
| CloudFront | CDN | 静的アセットキャッシュ、WAF 統合 |
| Route 53 | DNS | ホストゾーン管理、ヘルスチェック |
| ACM | SSL/TLS 証明書 | `*.propcloud.jp` ワイルドカード証明書 |
| S3 | ドキュメントストレージ | 帳票・画像の保存、暗号化有効 |
| SES | メール送信 | 請求書・督促メールの送信 |
| CloudWatch | 監視・ログ | メトリクス監視、ログ集約、アラート |
| WAF | Web アプリケーションファイアウォール | SQLi/XSS 保護、レート制限 |
| Secrets Manager | シークレット管理 | DB パスワード、API キー、JWT シークレット |
| リソース | CIDR / 設定 |
|---|---|
| VPC | `10.0.0.0/16` |
| パブリックサブネット(2 AZ) | `10.0.1.0/24`, `10.0.2.0/24` |
| プライベートサブネット(2 AZ) | `10.0.10.0/24`, `10.0.20.0/24` |
| DB サブネット(2 AZ) | `10.0.100.0/24`, `10.0.200.0/24` |
| NAT Gateway | パブリックサブネットに配置(各 AZ 1台) |
| グループ | インバウンド | 用途 |
|---|---|---|
| ALB SG | 80/443 (0.0.0.0/0) | インターネットからの HTTP/HTTPS |
| ECS SG | 3000 (ALB SG) | ALB からのトラフィックのみ |
| RDS SG | 5432 (ECS SG) | ECS タスクからの DB 接続のみ |
| Redis SG | 6379 (ECS SG) | ECS タスクからの Redis 接続のみ |
GitHub Actions と AWS CodePipeline を組み合わせたパイプラインを構築します。
GitHub (push/PR)
│
├── GitHub Actions(CI)
│ ├── リント(ESLint)
│ ├── 型チェック(TypeScript)
│ ├── ユニットテスト(Vitest)
│ ├── E2E テスト(Playwright)
│ └── Docker イメージビルド & ECR プッシュ
│
└── AWS CodePipeline(CD)
├── Source: ECR イメージ検知
├── Build: タスク定義更新
├── Deploy (dev): ECS Blue/Green デプロイ
├── Approval: 手動承認(本番のみ)
└── Deploy (prod): ECS Blue/Green デプロイ| ワークフロー | トリガー | 内容 |
|---|---|---|
| `ci.yml` | Push / PR (全ブランチ) | リント、型チェック、テスト |
| `build-push.yml` | Push (main ブランチ) | Docker ビルド、ECR プッシュ |
| `e2e.yml` | PR (main ブランチ) | Playwright E2E テスト |
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint-and-typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npx tsc --noEmit
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: propcloud_test
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx prisma generate
- run: npm run test:coverage
env:
DATABASE_URL: postgresql://test:test@localhost:5432/propcloud_test
build:
needs: [lint-and-typecheck, test]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-northeast-1
- uses: aws-actions/amazon-ecr-login@v2
- run: |
docker build -t $ECR_REGISTRY/propcloud:${{ github.sha }} .
docker push $ECR_REGISTRY/propcloud:${{ github.sha }}| ステージ | アクション | 設定 |
|---|---|---|
| Source | ECR イメージ | `propcloud` リポジトリの latest タグ |
| Build | CodeBuild | タスク定義の imageUri を更新 |
| Deploy-Dev | ECS Blue/Green | dev クラスターへデプロイ |
| Approval | 手動承認 | Slack 通知、本番デプロイ承認 |
| Deploy-Prod | ECS Blue/Green | prod クラスターへデプロイ |
ECS のブルーグリーンデプロイにより、ダウンタイムなしでアプリケーションを更新します。
┌─────────────────────────────────┐
│ ALB │
│ リスナールール │
└────────┬──────────┬──────────────┘
│ │
本番リスナー(443) テストリスナー(8443)
│ │
┌────▼────┐ ┌───▼─────┐
│ Blue TG │ │ Green TG │
│ (現行) │ │ (新版) │
└────┬────┘ └───┬─────┘
│ │
┌────▼────┐ ┌───▼─────┐
│ ECS │ │ ECS │
│ Tasks │ │ Tasks │
│ (v1.2) │ │ (v1.3) │
└─────────┘ └─────────┘1. **新バージョンのタスク起動**
- Green ターゲットグループに新バージョンの ECS タスクが起動される
- ヘルスチェック (`/api/health`) が通るまで待機
2. **テストリスナーで検証**
- テストリスナー(ポート 8443)経由で新バージョンにアクセス可能
- 自動テストまたは手動検証を実施
- 検証時間: 最大 60 分(設定可能)
3. **トラフィック切り替え**
- 本番リスナーを Green ターゲットグループに切り替え
- 全トラフィックが新バージョンに流れる
4. **旧バージョンの保持**
- 切り替え後、旧バージョン(Blue)のタスクは 60 分間保持
- 問題発生時は即座にロールバック可能
5. **旧バージョンの削除**
- 保持期間経過後、旧タスクが自動的に削除される
デプロイ後に問題が発生した場合:
# 1. CodeDeploy のデプロイメントを確認 aws deploy list-deployments \ --application-name propcloud-app \ --deployment-group-name propcloud-prod-dg \ --include-only-statuses Succeeded # 2. ロールバック(自動) # CodeDeploy のアラーム監視により、以下の条件で自動ロールバック: # - ヘルスチェック失敗 # - CloudWatch アラーム発火(エラー率 > 5%、レイテンシー p99 > 3s) # 3. 手動ロールバック aws deploy stop-deployment \ --deployment-id <deployment-id> \ --auto-rollback-enabled
| 条件 | 閾値 | 監視期間 |
|---|---|---|
| ヘルスチェック失敗 | 連続 3 回 | - |
| HTTP 5xx エラー率 | > 5% | 5 分間 |
| レスポンスタイム p99 | > 3,000 ms | 5 分間 |
| ECS タスク異常終了 | > 0 | デプロイ中 |
{
"deploymentConfig": {
"terminationWaitTimeInMinutes": 60,
"deploymentReadyOption": {
"actionOnTimeout": "CONTINUE_DEPLOYMENT",
"waitTimeInMinutes": 30
},
"blueGreenDeploymentConfiguration": {
"terminateBlueInstancesOnDeploymentSuccess": {
"action": "TERMINATE",
"terminationWaitTimeInMinutes": 60
}
}
}
}| 項目 | 開発 (dev) | 本番 (prod) |
|---|---|---|
| ECS タスク数 | 1 | 最小 2、最大 10 |
| RDS インスタンス | db.t4g.medium | db.r6g.large (Multi-AZ) |
| ElastiCache | cache.t4g.micro | cache.r6g.large |
| CloudFront | なし | 有効(WAF 統合) |
| 自動バックアップ | 1 日間 | 7 日間 |
| ログ保持 | 7 日間 | 90 日間 |
| デプロイ承認 | 不要(自動) | 必要(手動承認) |
| ドメイン | `dev.propcloud.jp` | `propcloud.jp` |