デプロイ¶
本番環境にデプロイする時に FastAPI アプリを起動する方法とかデプロイの自動化とか。
Info
uv のインストールが完了した Rocky Linux 9 にデプロイする前提で。
Uvicorn と Gunicorn¶
FastAPI をインストールしてれば、 Uvicorn も入ってるはず。
Note
fastapi dev コマンドと fastapi run コマンドは Uvicorn で FastAPI アプリを起動する。
ただ、 Uvicorn の公式ドキュメントで
Run gunicorn -k uvicorn.workers.UvicornWorker for production.
とあるので、 Gunicorn を使う。
さらに、 Uvicorn の公式ドキュメントには gunicorn で uvicorn ワーカーを使うときは、 uvicorn-worker を使うべきって書いてある。
Warning
The uvicorn.workers module is deprecated and will be removed in a future release. You should use the uvicorn-worker package instead.
uvicorn-worker を PyPI で検索すると、 gunicorn コマンドで使う時の例が書かれてる。
Deployment
For production environments, it's recommended to utilize Gunicorn with the Uvicorn worker class. Below is an example of how to do this:
Gunicorn を uvicorn-worker で動かすために uv コマンドでインストールしておく。
Gunicorn の起動設定¶
gunicorn コマンドで FastAPI アプリを起動する。
毎回このコマンドを打つのはめんどい・・・コンフィグファイルを作成して、起動時に読み込ませることができる。
# gunicorn_config.py
import multiprocessing
worker_class = "uvicorn_worker.UvicornWorker"
workers = multiprocessing.cpu_count() * 2 + 1
bind = "0.0.0.0:8000"
Info
FastAPI Cookbook (by Giunio De Luca, 2024) には、
A common heuristic is to use the formula workers = (2 x cores) + 1 , where cores means the number of CPU cores on the server.
— p.313 とあるので、 multiprocessing を使って自動で計算させるといいかも。
gunicorn コマンドで gunicorn_config.py を読み込んでFastAPI アプリを起動する。
Gunicorn はデーモンモード( -D, daemon = True)で起動することもできるけど、停止する時に kill コマンドを使う方法しか分からなくて微妙。
systemd で起動・停止できるようにも設定できるので、 systemd の設定ファイルを作成する。
[root@test ~]# vi /etc/systemd/system/fastapi-app.service
[Unit]
Description=Gunicorn instance to serve FastAPI App
After=network.target
[Service]
User=test
Group=test
WorkingDirectory=/home/test/my-fastapi-app
ExecStart=/home/test/.local/bin/uv run gunicorn -c gunicorn_config.py app.main:app
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
[root@test ~]# systemctl daemon-reload
これで、 systemctl コマンドで fastapi-app サービスを起動・停止できるようになる。
GitHub Actions を使った CD (Continuous Deploy) 実装¶
プロジェクトを GitHub でバージョン管理してるなら、 GitHub Actions を使ってデプロイの自動化ができる。
必要なのは YAML ファイルとローカルサーバーの設定、 YAML ファイルは .github/workflows/my-actions.yml のように作成する。
Warning
バグった状態でデプロイしないためにも、デプロイの前に pytest でテストを実行して成功したらデプロイするっていう自動化プロセスにするべき。
Warning
GitHub Actionsを狙った攻撃も実際にあった( https://tanstack.com/blog/npm-supply-chain-compromise-postmortem )ので、自動化するならプライベートリポジトリでやる方がいいはず。
-
YAMLファイル
# (YAMLファイルの例) name: CD without CI on: push: branches: [ "main" ] jobs: deploy: name: Deploy to Production runs-on: self-hosted steps: - name: Deploy checked commit run: | cd /home/test/my-fastapi-app previous_sha=$(git rev-parse HEAD) echo "PREVIOUS_SHA=${previous_sha}" >> "$GITHUB_ENV" git fetch origin main git checkout --detach "${{ github.sha }}" uv sync --frozen - name: Restart FastAPI Service run: sudo systemctl restart fastapi-app -
ローカルサーバーの設定
GitHubリポジトリ > Settings > Actions > Runners で表示される通りに設定を進める。