ガッツリ、はまりました。
FastAPIでつくったアプリをAzure App Serviceで実行しようとして嵌りましたので、解決までのメモを残します。
嵌った内容・状況は以下です。
- コンテナは使いたくない(軽くGitからデプロイしたい)
- デプロイセンターからの継続的ビルドは設定したくない (フォルダ構成が特殊)
- (デプロイセンターで継続的ビルドを設定した場合はなぜか動く)
- uvicorn not found となってuvicorn/gunicornが起動できない
必要だったもの(順番も)
Azure App Servcie のデプロイセンターから継続的ビルドを設定しない場合です。順番も結構重要です。特に2.と3.はデプロイするまでに設定しておく必要があります。
1. FastAPIのアプリを作成する
main.pyなりFastAPIのアプリをつくります。例えばこんなのですね。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
最低限 fastapi, uvicorn, gunicorn はインストールする必要があります。あとは、完成した pip freeze > requirements.txt で出力しておきます。
起動用のスタートアップスクリプトを準備します。
gunicorn --config gunicorn.py main:app
Gunicorn用の設定ファイルも外に出しておきます。例えばこんな感じです。
import multiprocessing
import os
name = "Gunicorn config for FastAPI"
bind = "0.0.0.0:8000"
worker_class = "uvicorn.workers.UvicornWorker"
workers = multiprocessing.cpu_count () * 2 + 1
上記だとファイル構成はこんな感じです。
$ ls
gunicorn.py main.py requirements.txt startup.sh
2. Azure App Service を作成する
Pythonのバージョンを指定して普通に作ります。特に何かを設定する必要はありません。
もしデプロイセンターから継続的ビルドを指定した場合は以下のステップのうち 3.スタートアップコマンドのみでOKです。
3. スタートアップコマンドを入れる
App Service の「構成」パネルからスタートアップコマンドを指定します。
ここまでの流れの場合は、startup.shを指定します。(コマンド直でも大丈夫です)
3. 環境変数として SCM_DO_BUILD_DURING_DEPLOYMENT を 1 にする
※ここが嵌りポイントでした
デプロイセンターから継続的ビルドを設定するとこれが設定されます。これを指定しないとrequirement.txtの内容をインストールできないため、これを指定します。
4. GitHub/Azure DevOps からデプロイする
3.までが完了してからデプロイをします。デプロイセンターから継続的ビルドをつくった場合のymlだとPython仮想環境のフォルダもデプロイされてしまうため、そこを省いた形で以下のようなものを作ります。(GitHub Actionsの場合)
run: zip release.zip ./* -r -x \*venv\*
-xでvenvフォルダを排除しています。
name: Build and deploy Python app to Azure Web App - shyamagu-fastapi
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python version
uses: actions/setup-python@v1
with:
python-version: '3.11'
- name: Create and start virtual environment
run: |
python -m venv venv
source venv/bin/activate
- name: Install dependencies
run: pip install -r requirements.txt
# Optional: Add step to run tests here (PyTest, Django test suites, etc.)yyy
- name: Zip artifact for deployment
run: zip release.zip ./* -r -x \*venv\*
- name: Upload artifact for deployment jobs
uses: actions/upload-artifact@v3
with:
name: python-app
path: |
release.zip
!venv/
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v3
with:
name: python-app
- name: Unzip artifact for deployment
run: unzip release.zip
- name: 'Deploy to Azure Web App'
uses: azure/webapps-deploy@v2
id: deploy-to-webapp
with:
app-name: {Azure App Service の名前}
slot-name: 'Production'
publish-profile: ${{ secrets.発行プロファイル }}
終わってみればまぁそうなんですが
Azure App Service で FastAPI というドキュメント自体があまり多くなく、嵌りましたのでメモとして残しました。
ポイントは、
- uvicorn はAzure App Service に標準で入っていないため、SCM_DO_BUILD_DURING_DEPLOYMENTでrequierments.txtを読み込むこと
- 設定全部が終わってからデプロイすること
- デプロイセンター標準のymlだとvenvフォルダもデプロイして無駄に容量使うので、省くこと
でしょうか。終わってみればまぁそうなんですが、タイミング問題もあってちょっとというかかなり嵌りましたということで。