付録C サーバ起動コマンド集
本付録では、Python Web アプリケーションを動かす代表的なサーバの起動コマンドを、開発用・本番用それぞれのパターンで紹介します。 付録 A・B で作成した最小アプリをそのまま使える形で示し、各オプションが「何を制御しているのか」を解説します。
注釈
本付録に登場するサーバは大きく WSGI 用と ASGI 用の 2 種類に分かれます。
サーバ |
対応プロトコル |
主な用途 |
|---|---|---|
Gunicorn |
WSGI(+ワーカー経由で ASGI も可) |
Django・Flask の本番運用 |
uWSGI |
WSGI |
既存の運用実績がある環境 |
Uvicorn |
ASGI |
FastAPI・Starlette の開発〜本番 |
Gunicorn + UvicornWorker |
ASGI |
FastAPI・Starlette の本番運用(推奨) |
どれを選ぶかは「アプリが WSGI か ASGI か」と「規模」によって決まります。
gunicorn
Gunicorn(Green Unicorn)は、WSGI アプリケーションのための本番グレードの HTTP サーバです。 pre-fork モデルを採用しており、マスタープロセスが複数のワーカープロセスを生成し、各ワーカーが独立してリクエストを処理します。
イメージとしては「親(マスター)が子(ワーカー)を監視し、子が止まったら新しい子を生む」仕組みです。
最小起動(開発確認用)
gunicorn app_hello:application
デフォルトでは 127.0.0.1:8000 にバインドし、ワーカー数は 1 です。
開発中の動作確認には十分ですが、本番ではワーカー数やタイムアウトの調整が必要になります。
本番向け起動
gunicorn app_json:application \
--bind 0.0.0.0:8000 \
--workers 4 \
--threads 2 \
--timeout 30 \
--graceful-timeout 10 \
--max-requests 1000 \
--max-requests-jitter 50 \
--access-logfile - \
--error-logfile - \
--log-level info
各オプションの意味は次のとおりです。
オプション |
意味 |
|---|---|
|
全インターフェースでリッスンします。リバースプロキシの背後に置く場合は UNIX ソケット( |
|
ワーカープロセス数です。目安は |
|
各ワーカー内のスレッド数です。IO バウンドな処理が多い場合に増やすと効果的です。ワーカー数 4 × スレッド数 2 で、同時に 8 リクエストを処理できます。 |
|
ワーカーが 30 秒以内に応答しない場合にマスタープロセスが強制終了して再起動します。ハングしたワーカーの検出に使います。 |
|
グレースフルシャットダウン(処理中のリクエストを完了させてから終了する)の猶予時間です。 |
|
ワーカーが指定回数のリクエストを処理した後に自動再起動します。メモリリークの蓄積を防止できます。 |
|
|
|
ログを標準出力に送ります。コンテナ環境では |
Tip
ワーカー数の目安 2 × CPUコア数 + 1 はあくまで出発点です。
CPU バウンドな処理(複雑な計算)が多いならコア数に合わせ、IO バウンドな処理(データベースやファイル待ち)が多いならスレッドを増やすほうが効果的な場合があります。
本番では負荷試験を行って最適値を探しましょう。
UNIX ソケットでの起動(nginx 連携)
gunicorn app_json:application \
--bind unix:/run/gunicorn.sock \
--workers 4 \
--timeout 30
nginx 側では proxy_pass http://unix:/run/gunicorn.sock; で接続します。
TCP ソケットと比べてネットワークスタックを経由しないため、同一ホスト上ではパフォーマンスが向上し、ポート管理も不要になります。
設定ファイルを使った起動
オプションが増えるとコマンドラインが長くなるため、Python ファイルに設定をまとめることもできます。
# gunicorn.conf.py
bind = "0.0.0.0:8000"
workers = 4
threads = 2
timeout = 30
graceful_timeout = 10
max_requests = 1000
max_requests_jitter = 50
accesslog = "-"
errorlog = "-"
loglevel = "info"
gunicorn app_json:application -c gunicorn.conf.py
便利な応用テクニック
設定ファイルは通常の Python コードとして実行されます。
そのため import multiprocessing して workers = multiprocessing.cpu_count() * 2 + 1 のように、CPU コア数に応じてワーカー数を動的に計算することも可能です。
環境ごとに設定を切り替えたい場合にも役立ちます。
uWSGI
uWSGI は多機能な WSGI/ASGI サーバで、Gunicorn より設定項目が多い分、細かな制御が可能です。 歴史的に広く使われてきましたが、近年は Gunicorn や Uvicorn を選択するプロジェクトが増えています。
注意
uWSGI プロジェクトは 2022 年頃にメンテナンスが停滞した時期があります。 新規プロジェクトへの導入前に、最新のメンテナンス状況を確認することをおすすめします。 既存の運用実績がある環境では引き続き利用できますが、これから始めるなら Gunicorn を選ぶのが無難です。
最小起動
uwsgi --http 127.0.0.1:8000 --wsgi-file app_hello.py --callable application
--http は uWSGI 自身が HTTP を話すモードです。nginx と連携する場合は --socket(uwsgi プロトコル)や --http-socket を使い分けます。
本番向け起動
uwsgi \
--http-socket 0.0.0.0:8000 \
--wsgi-file app_json.py \
--callable application \
--master \
--processes 4 \
--threads 2 \
--harakiri 30 \
--max-requests 1000 \
--vacuum \
--die-on-term \
--stats 127.0.0.1:9191
Gunicorn と比較したときの特徴的なオプションを以下にまとめます。
オプション |
意味 |
|---|---|
|
マスタープロセスを有効にします。Gunicorn ではデフォルト ON ですが、uWSGI では明示的に指定が必要です。 |
|
Gunicorn の |
|
終了時にソケットファイルや pid ファイルを自動削除します。 |
|
SIGTERM でクリーンに終了します。コンテナ環境で重要な設定です。 |
|
リアルタイム統計を JSON で配信するエンドポイントです。 |
警告
--die-on-term は uWSGI 特有の落とし穴に対処するための設定です。
uWSGI はデフォルトで SIGTERM を「終了」ではなく「リロード」と解釈するという独自仕様があります。
この設定を忘れると、コンテナ(Docker など)が停止コマンドを送っても uWSGI が終了せず、コンテナが強制終了(SIGKILL)を待つことになります。
コンテナで uWSGI を使う場合は必ず指定しましょう。
INI ファイルによる設定
; uwsgi.ini
[uwsgi]
http-socket = 0.0.0.0:8000
wsgi-file = app_json.py
callable = application
master = true
processes = 4
threads = 2
harakiri = 30
max-requests = 1000
vacuum = true
die-on-term = true
uwsgi --ini uwsgi.ini
nginx との連携(uwsgi プロトコル)
uwsgi --socket /run/uwsgi.sock --wsgi-file app_json.py --callable application --master --processes 4
nginx 側では uwsgi_pass unix:/run/uwsgi.sock; と include uwsgi_params; を設定します。
uwsgi プロトコルは HTTP より効率的なバイナリプロトコルで、nginx がネイティブにサポートしています。
uvicorn
Uvicorn は ASGI アプリケーションのための軽量・高速なサーバです。
内部で uvloop(libuv ベースのイベントループ)と httptools(Node.js の HTTP パーサーの Python バインディング)を使用しており、非同期処理に最適化されています。
最小起動(開発用)
uvicorn app_asgi:application --reload
--reload はファイル変更時の自動リロードを有効にします。
開発中は非常に便利な機能ですが、ファイルシステムの監視にリソースを使うため、本番環境では使ってはいけません。
警告
--reload は 開発専用 のオプションです。
本番環境で --reload を使うと、ファイルシステムの監視プロセスが常に走り続けてパフォーマンスが低下します。
また、アップロードされたファイルや設定ファイルが変更された際に意図せず再起動が発生するリスクもあります。
本番では必ず外してください。
本番向け起動
uvicorn app_asgi:application \
--host 0.0.0.0 \
--port 8000 \
--workers 4 \
--loop uvloop \
--http httptools \
--no-access-log \
--log-level warning
各オプションの補足です。
--workers 4: Uvicorn 0.17 以降で追加されたマルチワーカーモードです。内部的には Gunicorn と同様の pre-fork モデルを使います。--loop uvloop:uvloopをイベントループとして使用します。uvloopがインストールされていない場合はasyncioのデフォルトループにフォールバックします。Linux / macOS でpip install uvloopしておくと、パフォーマンスが大幅に向上します(Windows では動作しません)。--http httptools: HTTP パーサーとしてhttptoolsを使用します。ピュア Python 実装のh11より高速です。--no-access-log: アクセスログを無効にします。リバースプロキシ側でアクセスログを取っている場合、二重記録を防ぐために無効にすることがあります。
注釈
Uvicorn 単体の --workers は比較的新しい機能です。
Gunicorn のマスタープロセスが持つグレースフルリスタートやワーカー監視の成熟度には及ばない面があります。
小規模なデプロイであれば問題ありませんが、大規模な本番環境では次節の Gunicorn + UvicornWorker 構成を検討してください。
gunicorn + uvicorn worker
Gunicorn のプロセス管理能力と Uvicorn の ASGI 処理能力を組み合わせた構成です。 ASGI アプリケーションの本番デプロイにおける最も実績のある選択肢です。
「管理はベテランの Gunicorn に任せ、実際の仕事は速い Uvicorn がやる」という分業です。
基本の起動コマンド
gunicorn app_asgi:application \
-k uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--workers 4 \
--timeout 30 \
--graceful-timeout 10 \
--max-requests 1000 \
--max-requests-jitter 50 \
--access-logfile - \
--error-logfile -
重要
-k uvicorn.workers.UvicornWorker がこの構成の核心です。
Gunicorn はデフォルトで同期 WSGI 用の sync ワーカーを使いますが、-k でワーカークラスを差し替えることで、各ワーカープロセス内で Uvicorn の ASGI イベントループが動作するようになります。
この構成の分業は次のとおりです。
Gunicorn(マスター): ワーカーの生成・監視・再起動・シグナルハンドリングを担当
Uvicorn(各ワーカー内):
asyncな ASGI リクエスト処理を担当
UvicornWorker と UvicornH11Worker の違い
Uvicorn は 2 種類のワーカークラスを提供しています。
ワーカークラス |
内部実装 |
用途 |
|---|---|---|
|
|
本番環境で推奨される高速版 |
|
|
|
# uvloop が使えない環境向け(Alpine Linux イメージなど)
gunicorn app_asgi:application \
-k uvicorn.workers.UvicornH11Worker \
--bind 0.0.0.0:8000 \
--workers 4
設定ファイルとの組み合わせ
# gunicorn.conf.py
bind = "0.0.0.0:8000"
workers = 4
worker_class = "uvicorn.workers.UvicornWorker"
timeout = 30
graceful_timeout = 10
max_requests = 1000
max_requests_jitter = 50
accesslog = "-"
errorlog = "-"
loglevel = "info"
gunicorn app_asgi:application -c gunicorn.conf.py
設定ファイル内で worker_class を指定すれば、コマンドラインの -k は不要になります。
FastAPI / Starlette との組み合わせ
FastAPI アプリケーションの場合、エントリポイントの指定は通常の Uvicorn と同様です。
gunicorn main:app \
-k uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--workers 4
main:app は main.py 内の app = FastAPI(...) を指しています。
コマンド早見表
Tip
どのサーバを選べばよいか迷ったときは、この表を参考にしてください。
アプリの種類 |
環境 |
推奨サーバ |
|---|---|---|
WSGI(Django・Flask) |
本番 |
Gunicorn |
WSGI(Django・Flask) |
既存運用 |
uWSGI(既存設定を活かす場合) |
ASGI(FastAPI・Starlette・Django ASGI) |
本番(大規模) |
Gunicorn + UvicornWorker |
ASGI(FastAPI・Starlette) |
本番(小規模) |
Uvicorn 単体 |
WSGI / ASGI いずれも |
開発中 |
|
本付録で示した 4 つのサーバの使い分けをまとめると次のとおりです。
WSGI アプリ(Django・Flask)を本番で動かすなら Gunicorn が第一選択です。uWSGI は既存の運用実績がある場合に選択します。
ASGI アプリ(FastAPI・Starlette・Django ASGI)を本番で動かすなら Gunicorn + UvicornWorker が最も実績があります。小規模なら Uvicorn 単体でも十分です。
開発時はいずれのフレームワークも
--reload付きの Uvicorn や Django のrunserverで素早く確認し、本番では必ず上記のプロダクションサーバに切り替えましょう。
重要
どのサーバを選んでも、リバースプロキシ(nginx など)を前段に置くのが本番構成の基本です。 TLS 終端、静的ファイル配信、レート制限、バッファリングをリバースプロキシに任せることで、アプリケーションサーバは本来の仕事(リクエスト処理)に専念できます。
サーバの起動コマンドは「アプリケーションを動かす最後の一手」です。 その手前にある設計判断(ワーカー数・タイムアウト・プロセス管理)を理解したうえで選択することが重要です。