FastAPI本番デプロイ完全ガイド:Uvicornマルチワーカー・Docker・リバースプロキシで安心運用する方法
この記事のゴールと全体像
この記事では、開発用の uvicorn app.main:app --reload から一歩進んで、
- 本番運用で意識すべきポイント
- Uvicornのマルチワーカー機能を使ったASGIサーバの構成
- Dockerコンテナでのデプロイ
- Nginxなどのリバースプロキシの役割(HTTPSやヘッダの扱い)
といった「FastAPIを外に出すときに必ず通る道」を、なるべく具体的なサンプルと一緒に整理します。
公式ドキュメントでも、デプロイ時に意識すべき概念として「HTTPS・起動方法・再起動・レプリケーション(プロセス数)・メモリ」などが挙げられています。
この記事では、そうしたポイントを実際の設定例に落とし込んでいきますね。
誰が読んで得をするか(具体的ペルソナ)
個人開発・学習者さん(VPSや小さなクラウドに置きたい)
- 開発用のFastAPIアプリはできたけれど、「本番ではどう立ち上げればいいの?」が分からない。
- まずは小さなVPSやクラウド上で、自分だけ/少人数向けに安定して公開したい。
- Dockerはなんとなく触ったことがあるけれど、「FastAPIだとどう組み合わせるか」を知りたい。
→ Uvicornのマルチワーカー+Dockerでの最小構成を、具体的なコマンドとDockerfile付きで確認できます。
小規模チームのバックエンドエンジニアさん
- チームでFastAPIを採用していて、本番環境へのデプロイフローを整えたい。
- 1台〜数台のサーバで、Nginxなどのリバースプロキシを前段に置いた構成を検討している。
- リロード・再起動・プロセス数・ヘルスチェックなど、運用を意識した構成のイメージを掴みたい。
→ 「Uvicornマルチワーカー+Nginx(またはTraefikなど)+Docker」の役割分担を整理できます。
SaaS開発チーム・スタートアップの皆さま
- 将来的にはKubernetesやマネージドコンテナサービスでスケールさせたい。
- まずは単一コンテナの構成から始めつつ、「あとからクラスタ側でレプリケーションする」前提で設計したい。
- Gunicorn型の複雑な構成ではなく、できるだけシンプルな構成で始めたい。
→ 最新のUvicornではマルチプロセス実行が内蔵されており、「必ずしもGunicornを挟む必要はない」という現状を踏まえつつ、将来のスケールを見据えた基本形を確認できます。
アクセシビリティ評価(読みやすさ・理解のしやすさ)
- 構造:
- 「デプロイの全体像」→「Uvicornの本番設定」→「Docker化」→「リバースプロキシ」→「運用・監視」→「ロードマップ」という段階構成で、必要なところだけ拾い読みしやすいようにしました。
- 用語:
- ASGIサーバ・ワーカー・リバースプロキシといった用語は、初出時に短く説明し、その後は同じ言葉を繰り返しています。
- コード:
- Dockerfileや設定ファイルは、1ブロックを短めに分け、コメントも最小限にして視線が迷わないように工夫しました。
- 想定読者:
- FastAPIのチュートリアルを一通り終えた方を想定しつつ、章ごとに独立して読めるようにしています。
目標としては、技術記事としてWCAG AA程度のアクセシビリティ水準を意識しています。
1. 本番デプロイで押さえるべき「概念」
まずは、具体的なコマンドに入る前に、「何を考えて構成を決めるか」を簡単に整理します。
1.1 デプロイで意識したいポイント
-
HTTPS
- ブラウザやクライアントからの通信を暗号化する。
- 多くの場合、NginxやTraefikなどのリバースプロキシが証明書を管理します。
-
起動と再起動
- サーバが再起動しても、自動的にアプリが立ち上がる。
- プロセスが落ちたときに、再起動してくれる仕組み(systemd / コンテナオーケストレーションなど)。
-
レプリケーション(プロセス数)
- CPUコアを活かすために、1つのアプリを複数プロセスで動かす。
- Uvicorn本体の
--workersや、クラスタ側(Kubernetes等)でのPod複製で対応。
-
メモリ・リソース
- 1プロセスあたりのメモリ使用量を意識しつつ、「何プロセスまで増やせるか」を考える。
これらをバラバラに見るのではなく、
「FastAPIアプリ(Uvicorn)」「リバースプロキシ(Nginx等)」「OS or コンテナオーケストレーション」
の3レイヤーに役割を分けて考えると、頭の整理がしやすくなります。
2. Uvicornの本番用起動:マルチワーカーと基本オプション
以前は、「本番ではGunicorn+UvicornWorkerで動かす」というパターンがよく紹介されていましたが、
最近のUvicorn(0.30以降)にはマルチプロセスのスーパーバイザが内蔵されており、--workers オプションだけで複数プロセスを起動できます。
2.1 最小の本番用コマンド例
開発時のよくあるコマンド:
uvicorn app.main:app --reload
本番を意識したシンプルな例:
uvicorn app.main:app \
--host 0.0.0.0 \
--port 8000 \
--workers 4
ここでのポイントは、
--reloadを外す(コード変更監視は本番では不要・危険)--host 0.0.0.0で外部からアクセス可能にする(コンテナ内やVPS上で)- CPUコア数を見ながら
--workersを設定する(例:コア数と同じ〜2倍程度から試す)
という3点です。
2.2 Uvicornの追加オプション例
-
--limit-concurrency- 同時処理数を制限して、メモリやCPUの暴走を抑えます。
-
--limit-max-requests- ワーカーが処理するリクエスト数の上限を決め、一定数を超えたら再起動することでメモリリークを軽減します。
-
--proxy-headers- NginxやTraefikなどのリバースプロキシの背後で動かすときに、元のクライアントIPやスキーム(HTTP/HTTPS)を正しく認識するためのオプションです。
例:
uvicorn app.main:app \
--host 0.0.0.0 \
--port 8000 \
--workers 4 \
--proxy-headers \
--limit-max-requests 10000
3. DockerでFastAPIアプリをコンテナ化する
最近は、DockerコンテナとしてFastAPIアプリをデプロイするケースがとても多いです。
公式ドキュメントでも、「FastAPI in Containers – Docker」としてDockerfileのテンプレートが紹介されています。
3.1 もっともシンプルなDockerfileの例
公式ドキュメントの流れを参考に、FastAPI CLIを使う形のDockerfile例です。
# ベースとなるPythonイメージ
FROM python:3.11-slim
# 作業ディレクトリ
WORKDIR /code
# 依存パッケージをコピー
COPY ./requirements.txt /code/requirements.txt
# 依存パッケージをインストール
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# アプリケーションコードをコピー
COPY ./app /code/app
# 本番用の起動コマンド
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
requirements.txt には、例えば次のようなパッケージが入ります。
fastapi[standard]>=0.113.0,<0.114.0
uvicorn>=0.30.0,<0.31.0
sqlalchemy>=2.0.0,<3.0.0
コンテナのビルドと実行:
docker build -t my-fastapi-app .
docker run -d --name my-fastapi -p 8000:80 my-fastapi-app
これで、ホストの http://localhost:8000 からアプリにアクセスできるようになります。
3.2 シンプルなUvicorn起動に変えるパターン
FastAPI CLIの代わりに、直接Uvicornを使ってもOKです。
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "4"]
コンテナでは、基本的に「1コンテナ=1プロセス」が推奨されており、
プロセス数(ワーカー数)は --workers で調整し、複数コンテナの複製はKubernetesなどのオーケストレーター側に任せる、という考え方が一般的です。
4. Nginxなどのリバースプロキシと組み合わせる
多くの構成では、FastAPI(Uvicorn)はHTTPのバックエンドとして動き、
その前段にNginxやTraefikが立ってHTTPS終端やロードバランシングを担当します。
4.1 なぜリバースプロキシを置くのか
-
HTTPS証明書の管理
- Let’s Encryptなどの証明書更新処理を、Nginx/Traefik側でまとめて扱える。
-
静的ファイル・画像配信
- 画像やCSS、JavaScriptの配信を、軽量なHTTPサーバ(Nginx)に任せる。
-
ロードバランシング
- 複数のFastAPIコンテナ、あるいは複数サーバにリクエストを分散できる。
-
セキュリティ・制限
- IP制限・Rate Limit・Basic認証など、ネットワークレベルの制御をプロキシ側で実施できる。
4.2 シンプルなNginx設定例(1台構成)
FastAPI(Uvicorn)がローカルの 127.0.0.1:8000 で動いている前提の、Nginx設定例です。
# /etc/nginx/conf.d/myapp.conf のイメージ
server {
listen 80;
server_name example.com;
# HTTP → HTTPSにリダイレクトする場合はここで301返却など(省略可)
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Uvicorn側は --proxy-headers を付けておくことで、これらのヘッダを解釈し、
実際のクライアントIPやプロトコル(HTTPS)を正しくアプリに伝えられるようになります。
4.3 コンテナでNginxとFastAPIを組み合わせる例
Docker Composeなどを使うと、FastAPIコンテナとNginxコンテナを別々に定義し、
NginxからFastAPIコンテナへ proxy_pass http://fastapi:8000; のように名前解決させる構成がよく使われます。
5. 本番向けの環境変数と設定管理
デプロイ時に重要なのが、「環境別の設定切り替え」です。
5.1 環境ごとに変わるもの
- データベース接続文字列
- APIキーやシークレット
- デバッグフラグ(
DEBUG=True/False) - ログレベル(INFO / DEBUG / WARNING)
これらは、コードにベタ書きせず、環境変数から読み込むのが基本です。
5.2 pydantic-settings(Settings管理)との組み合わせ
以前の記事でも触れたような pydantic-settings を使うと、
.env- 環境変数
- デフォルト値
をまとめて扱えるようになります。
# app/core/settings.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "My FastAPI App"
environment: str = "dev"
database_url: str
secret_key: str
log_level: str = "info"
class Config:
env_file = ".env"
settings = Settings()
本番環境では .env ではなく、実際の環境変数(例:SECRET_KEY)をセットし、
開発環境では .env で補う、という運用が多いです。
コンテナであれば、
docker run -d \
-e ENVIRONMENT=prod \
-e DATABASE_URL=postgresql+psycopg://... \
-e SECRET_KEY=... \
-p 8000:80 my-fastapi-app
のように、-e オプションで環境変数を渡せます。
6. 健全な運用のための監視・再起動戦略
ここまでで「どう起動するか」を見てきましたが、
本番運用では「落ちたときどうするか」「負荷が増えたときどう気づくか」も大切です。
6.1 systemdでの常駐管理(VPSでDockerを使わない場合)
VPSに直接Uvicornを立てる場合、
systemdのサービスとして登録- プロセスが落ちたら自動で再起動
- サーバ起動時に自動で立ち上がる
といった設定が一般的です。
簡易的な my-fastapi.service の例:
[Unit]
Description=My FastAPI application
After=network.target
[Service]
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/local/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4 --proxy-headers
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
systemctl enable my-fastapi → systemctl start my-fastapi で自動起動・再起動が有効になります。
6.2 コンテナオーケストレーション側での再起動・スケーリング
Docker Compose / Kubernetes / ECS などを使う場合、
- コンテナが落ちたときの自動再起動
- コンテナのレプリカ数(横方向スケール)
- ヘルスチェック(/health などのエンドポイント)
を、オーケストレーション側で設定します。
FastAPI側では、シンプルなヘルスチェックエンドポイントを用意しておくと便利です。
# app/api/health.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/health", tags=["health"])
def health_check():
return {"status": "ok"}
7. サンプル:Docker+Uvicorn+Nginxのミニ構成
ここまでの話を組み合わせた、小さな構成例をイメージとしてまとめてみます。
7.1 ディレクトリ構造の例
project/
app/
__init__.py
main.py
api/
health.py
...
requirements.txt
docker-compose.yml
Dockerfile
nginx/
default.conf
7.2 Dockerfile(FastAPIコンテナ)
FROM python:3.11-slim
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4", "--proxy-headers"]
7.3 Nginxコンテナ用設定
# nginx/default.conf
server {
listen 80;
server_name _;
location / {
proxy_pass http://fastapi:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
7.4 docker-compose.yml
version: "3.9"
services:
fastapi:
build: .
container_name: fastapi-app
environment:
- ENVIRONMENT=prod
- DATABASE_URL=sqlite:///./app.db
expose:
- "8000"
nginx:
image: nginx:1.27
container_name: nginx-proxy
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- fastapi
この構成で docker-compose up -d --build すれば、
http://localhost/へのアクセスはNginxを通り、- Nginxが
fastapi:8000にプロキシ、 - FastAPI(Uvicorn)が実際のアプリを処理、
という流れで動作します。
8. よくあるつまずきポイントと対策
最後に、本番デプロイでよくハマりがちなポイントを、簡単な対策と一緒に整理しますね。
| 症状 | 原因 | 対策 |
|---|---|---|
| クライアントIPがすべて127.0.0.1 | Nginxなどのプロキシを挟んでいるのに、X-Forwarded-For を解釈していない |
Nginx側のヘッダ設定を見直しつつ、Uvicornを --proxy-headers 付きで起動する |
| HTTPとHTTPSでリンク先が混在 | プロキシとバックエンドのURL意識がズレている | プロキシ側で X-Forwarded-Proto を正しく渡し、FastAPI側でそれを尊重する |
| デプロイ後だけエラーが出る | 環境変数やデータベース設定が本番では異なる | 環境ごとの差分を「設定クラス+ENV」で一元管理し、ローカルでも本番と同じ形で動かしてみる |
| 負荷がかかると急に落ちる | ワーカー数やコンテナ数が足りない、あるいはメモリ不足 | まずはメトリクスでCPU・メモリ使用率とレイテンシを観察し、少しずつ --workers やコンテナ数を増やす |
| どの構成が正解か分からない | デプロイ方法が多すぎて迷子状態 | まずは「Uvicornマルチワーカー+Docker+シンプルなリバースプロキシ」の最小構成から始め、必要になったらKubernetes等に広げる |
9. 導入ロードマップ(少しずつ本番構成に近づける)
最後に、「これからFastAPIアプリを本番に出していくときのステップ」を、段階的にまとめておきます。
-
ローカルでの開発
uvicorn app.main:app --reloadで機能を実装。- テストやロギングの仕組みをある程度整える(pytest・構造化ログなど)。
-
Uvicornマルチワーカーでの起動を試す
--reloadを外して、本番に近い設定でローカル動作を確認。--workers・--limit-max-requestsなどのオプションも試して、挙動を掴む。
-
Docker化する
- 公式ドキュメントを参考にDockerfileを用意し、コンテナ化したFastAPIアプリをローカルで動かす。
docker-composeでDBや他サービスとのつなぎ込みを試す。
-
リバースプロキシとの組み合わせ
- まずはHTTPのみでNginx/TraefikからFastAPIコンテナへのプロキシを構成する。
- 必要に応じてHTTPS終端や静的ファイルの扱いも整理する。
-
本番環境へのデプロイ
- VPSやクラウド(ECS・GKEなど)にDockerイメージをデプロイし、ヘルスチェック・ログ・メトリクスを整える。
- 負荷試験を行い、ワーカー数やコンテナ数を少しずつ調整する。
-
将来的なスケール
- 必要になった段階で、Kubernetesなどのオーケストレーションツールに移行し、「スケールはクラスタ側で、コンテナ内はシンプルに」という方針に寄せていく。
まとめ
- 本番デプロイでは、「HTTPS・起動と再起動・レプリケーション・メモリ」といった観点から、FastAPIアプリの構成を考えることが大切です。
- Uvicornは最新バージョンでマルチワーカー機能を内蔵しており、
--workersオプションだけで複数プロセスを起動できます。シンプルな構成から始めたい場合は、この機能を軸にして構成を組み立てるのがおすすめです。 - Docker化することで、開発環境と本番環境の違いを減らし、デプロイの再現性を高めることができます。リバースプロキシ(Nginx/Traefik)と組み合わせれば、HTTPSや静的ファイル配信、ロードバランシングも整理しやすくなります。
- いきなり完璧な構成を目指す必要はありません。まずは「Uvicornマルチワーカー+Docker」の最小構成から始め、必要になったところから少しずつプロキシやオーケストレーションを取り入れていく流れが、心にもインフラにも優しいと思います。
あなたのFastAPIアプリが、安心して外の世界に出ていけるように、
そして「壊れてもすぐ立て直せる」柔らかい本番構成に育っていくように、この記事が少しでもお役に立てていたらうれしいです。
どうぞ、無理のないペースで、一歩ずつ試してみてくださいね。

