はじめに
holocollect で収集したホロライブの配信予定や動画情報を API として提供する holoservice を、Ubuntu VM 上で動かしていましたが、holocollect 側のコンテナ化と MongoDB Atlas への移行を進める中で、holoservice も同じ方向で整理したくなりました。
今回やったことは次のとおりです。
- MongoDB の接続先を MongoDB Atlas に合わせて整理
- holoservice を Docker イメージ化
- Azure Container Apps へデプロイ
- FastAPI ベースの API を Azure 上で公開
- 必要に応じて NAT Gateway あり / なしの構成を選べるようにする
この記事では、holoservice 編として、考え方と Azure デプロイ手順をまとめます。
対象のリポジトリはこちらです。
holoservice の役割
holoservice は、MongoDB に登録されている配信情報や配信者情報を API として提供する FastAPI アプリです。
主な役割は次のとおりです。
- 配信情報の参照
- 配信者情報の参照
- ユーザー認証
- JWT による保護 API の提供
holocollect が定期実行バッチなのに対して、holoservice は常駐させる HTTP API です。
この違いがあるので、Azure 側でも holocollect は Job、holoservice は通常の Container App に分けています。
移行前後の構成
移行前
- Ubuntu VM
- FastAPI / uvicorn で API を起動
- MongoDB も含めて VM 寄りの構成
- デプロイや公開設定も VM 側で調整
移行後
- MongoDB Atlas を利用
- holoservice を Docker 化
- Azure Container Registry にイメージ登録
- Azure Container Apps で API を常駐公開
- 用途に応じて external / internal ingress を選択
なぜ Azure Container Apps にしたのか
holoservice は FastAPI で動く Web API なので、常駐させる前提の実行基盤が必要です。
Azure Container Apps を選んだ理由は次のとおりです。
- Docker 化した FastAPI を素直に動かせる
- Ingress 設定で公開範囲を調整しやすい
- Azure 上で API を比較的シンプルに公開できる
- VM のプロセス管理から離れられる
特に個人開発や小規模サービスでは、AKS まで行かずに扱えるのがかなりよかったです。
MongoDB Atlas へ寄せたメリット
holoservice 側でも、MongoDB Atlas を使うメリットは大きかったです。
1. API と DB の責務を分けやすい
アプリは API 提供に集中し、DB 基盤は Atlas に任せる形になります。
2. デプロイ先の自由度が上がる
Ubuntu VM に DB が張り付いていると、アプリ移行の足かせになりがちです。
接続先が Atlas なら、アプリ側はコンテナとして素直に持ち出せます。
3. シークレット管理に寄せやすい
MONGO_URI や JWT_SECRET_KEY などを、Container Apps 側の secret / env-vars へ流し込みやすくなります。
事前準備
ローカル環境
- Windows 11
- PowerShell 7
- Azure CLI
- Docker Desktop もしくは az acr build を使える環境
- Git
- holoservice リポジトリ
Azure 側
- Azure アカウント
- リソース作成権限
- Azure CLI ログイン済み
確認コマンド:
az login
az account show
MongoDB Atlas 側
- クラスター作成済み
- 接続ユーザー作成済み
- 接続文字列取得済み
.env の準備
holoservice でも、設定は .env ベースにしておくとローカルと Azure の差分を減らせます。
例:
MONGO_URI="mongodb+srv://[user]:[password]@[cluster-url]/holoduledb"
MONGO_DATABASE="holoduledb"
JWT_SECRET_KEY="[JWT secret]"
JWT_ALGORITHM="HS256"
JWT_EXP_DELTA_MINUTES=15
CORS_ALLOWED_ORIGINS=""
ポイント:
- MONGO_URI は Atlas の接続文字列を使う
- JWT_SECRET_KEY は十分長い値にする
- CORS はブラウザから直接呼ぶ場合だけ設定する
- Postman や server-to-server 利用だけなら CORS を空でもよい
Docker 化で意識したこと
holoservice は FastAPI / uvicorn ベースなので、holocollect よりはコンテナ化しやすい構成です。
意識したポイントは次のとおりです。
- uvicorn で起動する FastAPI アプリとしてまとめる
- ローカル起動と Docker 起動で挙動差を減らす
- JWT や DB 接続文字列をコードへ直書きしない
- Azure 公開時に Ingress を切り替えられるようにする
Azure デプロイの考え方
holoservice では、用途に応じて 2 種類のデプロイスクリプトを用意しています。
NAT なし版
- スクリプト: infra/deploy-container-app.ps1
- 低コスト
- VNet / NAT Gateway を使わない
- MongoDB Atlas 側は広めの IP 許可が必要
NAT あり版
- スクリプト: infra/deploy-container-app-nat.ps1
- 固定送信元 IP を使える
- VNet / Subnet / NAT Gateway / Public IP を構成
- Atlas 側で Allow List を絞りやすい
どちらを選ぶかは、セキュリティ要件とコストのバランス次第です。
Azure デプロイ手順
ここでは、まずシンプルな NAT なし版、その後に NAT あり版も説明します。
1. NAT なし版でデプロイする
最小コマンドは次のとおりです。
.\infra\deploy-container-app.ps1 `
-ResourceGroup rg-holoservice `
-RegistryName holoserviceacr
このスクリプトで、主に次の処理が行われます。
- Resource Group 作成
- Azure Container Registry 作成または更新
- az acr build で Docker イメージをビルド
- Container Apps Environment を作成または再利用
- holoservice 用の Container App を作成
この構成はシンプルで試しやすいですが、送信元 IP は固定されません。
そのため、MongoDB Atlas 側では一時的に 0.0.0.0/0 許可などが必要になります。
2. NAT あり版でデプロイする
固定送信元 IP を使いたい場合は、次のスクリプトを使います。
.\infra\deploy-container-app-nat.ps1 `
-ResourceGroup rg-holoservice `
-RegistryName holoserviceacr
このスクリプトでは、次の処理まで含めて実行します。
- VNet / Subnet の作成または再利用
- NAT Gateway の作成または再利用
- 固定 Public IP の作成
- Container Apps Environment の VNet 統合
- Container App の作成
完了後に NAT Public IP が表示されるので、それを MongoDB Atlas の Network Access に /32 で登録します。
3. Ingress を選ぶ
holoservice は API なので、Ingress の考え方も大事です。
主な選択肢は次のとおりです。
- external: 外部公開する
- internal: Azure 内部からのみ利用する
たとえば、Postman で疎通確認したい段階では external がわかりやすいです。
今後、別のバックエンドからのみ利用するなら internal も検討できます。
作り直し例:
.\infra\deploy-container-app.ps1 `
-ResourceGroup rg-holoservice `
-RegistryName holoserviceacr `
-Ingress internal `
-ForceRecreateApp
4. Container App に渡す設定
デプロイ時には主に次の設定を Azure 側へ渡します。
- MONGO_URI
- MONGO_DATABASE
- JWT_SECRET_KEY
- JWT_ALGORITHM
- JWT_EXP_DELTA_MINUTES
- CORS_ALLOWED_ORIGINS
機密値は secret 扱いに寄せ、アプリ側では環境変数から読む形にしておくと管理しやすいです。
5. デプロイ後に Swagger を確認する
Container App が起動したら、まず Swagger を確認すると API の公開状態が把握しやすいです。
https://[your-container-app-url]/docs
ここで次を確認します。
- FastAPI が起動している
- ルーティングが見えている
- 認証 API が利用できる
- 保護 API にトークン付きでアクセスできる
Postman での確認
Swagger でも確認できますが、Postman での疎通確認もしやすいです。
1. トークン取得
POST /token
フォームデータ:
username=<username>
password=<password>
2. Bearer トークン付きで API 呼び出し
Authorization: Bearer <access_token>
たとえば、配信情報一覧やユーザー情報の API を叩いて確認できます。
よく使う主なパラメーター
共通でよく使うのは次のあたりです。
- -Location
- -EnvFile
- -ContainerAppsEnvironment
- -AppName
- -Ingress
- -TargetPort
- -Cpu
- -Memory
- -ForceRecreateApp
必要に応じて、NAT あり版では VNet や NAT Gateway 関連のパラメーターも上書きできます。
ハマりやすかったポイント
1. NAT を使うかどうかを最初に決める
MongoDB Atlas の接続元制御を厳密にしたいなら NAT あり、低コスト優先なら NAT なしです。
後から切り替えることもできますが、最初に考えを決めておくと楽です。
2. CORS は必要なときだけ有効にする
ブラウザから直接呼ばないなら、無理に広げないほうが安全です。
3. external / internal Ingress の意図を混ぜない
公開 API なのか、内部 API なのかで設計が変わるので、運用イメージに合わせて選ぶのが大事です。
4. まずは Swagger と Postman で確認する
いきなりフロントエンドとつなぐより、先に API 単体で正常性を確認したほうが切り分けしやすいです。
おわりに
今回は、Ubuntu VM で動かしていた holoservice を、Docker 化したうえで Azure Container Apps に移行し、MongoDB Atlas を利用する構成へ整理しました。
holocollect が Job 向きだったのに対して、holoservice は常駐 API なので、Azure Container Apps の通常のアプリ構成がよく合っていました。
今回の移行で、
- DB は MongoDB Atlas
- バッチ処理は Azure Container Apps Job
- API は Azure Container Apps
と役割ごとにきれいに分けられたのはかなり大きかったです。
Ubuntu VM のように 1 台へ寄せる構成は自由度がある一方で、運用責務も集まりがちです。今回のように、責務ごとにマネージド寄りの構成へ整理すると、個人開発でもかなり扱いやすくなると感じました。
同じように、FastAPI アプリを VM で運用していて、デプロイや公開の手順をもう少しシンプルにしたい場合は、Azure Container Apps はかなり相性がよい選択肢だと思います。