インフラストラクチャ
環境一覧
| 環境 | Web | API | 用途 |
|---|---|---|---|
| 本番 | 未構築 | 未構築 | 本番サービス |
| dev | https://survey-design-web.heineken.dev.4digit.ai | https://survey-design-api.heineken.dev.4digit.ai | 動作確認・統合テスト。チームの共有環境 |
| ローカル | http://localhost:3000 | http://localhost:8787 | ローカル開発 |
dev は共有環境
dev には他メンバーの実データが入っています。統合テストは毎回新しい案件を作る運用のため、溜まってきたら integration-tests の bun run cleanup で削除してください。dev API は x-user-email + x-user-name ヘッダだけで叩けます。
構成図
graph TD
User[調査設計担当者]
Ext[Chrome 拡張]
Google[Google OAuth]
AppRunner[AWS App Runner<br/>frontend Next.js]
APILambda[AWS Lambda<br/>backend API]
MigLambda[AWS Lambda<br/>マイグレーション]
DB[(PostgreSQL)]
ECR[Amazon ECR]
GHA[GitHub Actions]
CS[(Creative Survey)]
User --> AppRunner
Google -.-> AppRunner
AppRunner --> APILambda
Ext --> APILambda
Ext --> CS
APILambda --> DB
MigLambda --> DB
GHA --> ECR
ECR --> AppRunner
ECR --> APILambda
ECR --> MigLambda
主要サービス一覧
| サービス名 | 用途 |
|---|---|
| AWS App Runner | frontend(Next.js)のホスティング。コンテナイメージから起動する |
| AWS Lambda | backend API のホスティング。コンテナイメージ(public.ecr.aws/lambda/nodejs:22 ベース)で動作する |
| AWS Lambda(マイグレーション) | Drizzle のマイグレーションを実行する。API とは別関数として分離されている |
| Amazon ECR | 3 種類のコンテナイメージ(web / backend / migration)のレジストリ |
| PostgreSQL | メインデータベース |
| GitHub Actions | ビルドと ECR への push、デプロイの実行 |
リージョンは ap-northeast-1(東京)。
コンポーネントとリポジトリ
| コンポーネント | 実行環境 | ECR リポジトリ(dev) | Lambda / サービス名(dev) |
|---|---|---|---|
| frontend(web) | App Runner | dev-heineken-survey-design-web |
dev-heineken-survey-design-web |
| backend API | Lambda | dev-heineken-survey-design-backend |
dev-heineken-survey-design-backend |
| マイグレーション | Lambda | dev-heineken-survey-design-backend-migration |
dev-heineken-survey-design-backend-migration |
コンテナイメージ
backend API(Dockerfile)
| ステージ | 内容 |
|---|---|
build(oven/bun) |
依存をインストールし、bun build src/lambda.ts で CommonJS 形式にバンドルする |
実行(public.ecr.aws/lambda/nodejs:22) |
バンドル結果・node_modules・drizzle/・openapi.json を配置し、lambda.handler を起動する |
postgres パッケージのみバンドル対象外(--external postgres)とし、node_modules から読み込む。
マイグレーション(Dockerfile.migration)
構成は API とほぼ同じで、エントリーポイントが migrate-handler.handler になる。postgres と drizzle-orm をバンドル対象外とする。
frontend(Dockerfile)
oven/bun をベースにした 3 ステージ構成(deps / build / release)。ポート 3000 で next start を実行する。
NEXT_PUBLIC_API_URL を ビルド引数として埋め込む ため、接続先 API を変更する場合はイメージの再ビルドが必要。
デプロイフロー
| ブランチ | デプロイ先 | タイミング |
|---|---|---|
main(backend) |
dev の API Lambda | 自動(push 時) |
main(backend、drizzle/** 変更時) |
dev のマイグレーション Lambda | 自動(push 時)または手動実行 |
main(frontend) |
dev の App Runner | 自動(push 時) |
backend: Dev Deploy
graph LR
Push[main への push] --> Checkout[チェックアウト]
Checkout --> Creds[AWS 認証情報の設定]
Creds --> Login[ECR ログイン]
Login --> Build[docker build]
Build --> PushImg[ECR へ push<br/>タグ: コミット SHA と latest]
PushImg --> Update[aws lambda update-function-code]
backend: Dev Migration
drizzle/** の変更を含む main への push、または手動実行(workflow_dispatch)で動く。
- マイグレーション用イメージをビルドして ECR へ push する
- マイグレーション Lambda が存在するか確認する(存在しなければ以降をスキップ)
- Lambda のイメージを更新し、更新完了を待つ
- Lambda を実行し、ログを出力する
マイグレーションを分離している理由
API Lambda はリクエストごとに起動するため、起動時にマイグレーションを実行すると多重実行になる。独立した Lambda として明示的に 1 回だけ呼び出す構成にしている。
frontend: Dev Deploy
NEXT_PUBLIC_API_URLをビルド引数に指定してイメージをビルドする- ECR へ push する(タグ: コミット SHA と
latest) aws apprunner start-deploymentで App Runner のデプロイを開始する
必要な GitHub Secrets
| シークレット | 用途 |
|---|---|
AWS_ACCESS_KEY_ID |
ECR / Lambda / App Runner の操作 |
AWS_SECRET_ACCESS_KEY |
同上 |
環境変数
backend
| 変数名 | 用途 |
|---|---|
DATABASE_URL |
PostgreSQL の接続文字列。sslmode=no-verify を含む場合は証明書検証を無効化して接続する |
SURVEY_ADMIN_EMAILS |
管理者のメールアドレス(カンマ区切り) |
SURVEY_IMPORT_API_KEY |
取り込み API の API キー。未設定ならキー認証は無効 |
frontend
| 変数名 | 用途 |
|---|---|
NEXTAUTH_URL |
next-auth のベース URL |
NEXTAUTH_SECRET |
セッション暗号化キー |
GOOGLE_CLIENT_ID |
Google OAuth のクライアント ID |
GOOGLE_CLIENT_SECRET |
Google OAuth のクライアントシークレット |
NEXT_PUBLIC_API_URL |
backend API のベース URL(ビルド時に埋め込まれる) |
認証・アクセス経路
| 経路 | 認証方式 |
|---|---|
| ユーザー → frontend | next-auth の Google ログイン。/surveys/* と /library/* を middleware で保護 |
| frontend → backend | x-user-email / x-user-name / x-user-image ヘッダによるユーザー情報の受け渡し |
| Chrome 拡張 → backend(取り込み) | x-api-key ヘッダによる API キー認証(SURVEY_IMPORT_API_KEY と照合) |
| Chrome 拡張 → CS | CS 編集画面のセッションをそのまま利用する |
backend は CORS をすべてのオリジンに対して許可し、Content-Type / x-user-email / x-user-name / x-user-image / x-api-key ヘッダを受け付ける。
既知の課題
本番展開前に対応が必要な、確認済みの問題。
| 課題 | 内容 |
|---|---|
| 認証のなりすまし | backend の認証が x-user-email ヘッダを信頼する方式のため、ヘッダを詐称すれば任意のユーザーとして操作できる |
| 権限チェックの迂回 | importSection のスナップショット直読みフォールバックが権限チェックを通らない(survey-store.ts) |
| CORS の全許可 | origin: "*" で全オリジンを許可している |
| 既定ユーザーの自動作成 | DEFAULT_ACTORS(@survey.local)が本番環境でも自動作成される |
| Makefile の不在 | 各 README の make コマンドに対応する Makefile が存在しない |