Nginx<->uWSGI<->Flask
Web ブラウザからの HTTP リクエストを受け取って Flask アプリケーションに処理を渡す流れ
(ブラウザ)
↓
(Nginx)
↓ (uWSGIプロトコル)
(uWSGI)
↓
(Flaskアプリ)
1. Nginx の設定
Nginx から uWSGI への連携設定
Nginx 側では、server
ブロックの中で location
ディレクティブを使ってリクエストをどこへ転送するか設定します。典型的には次のようになります。(パスやファイル名は例です。)
# /etc/nginx/conf.d/myapp.conf (あるいは sites-available/myapp.conf など)
server {
listen 80;
server_name example.com; # ドメインまたはIP
location / {
include uwsgi_params; # uWSGIのパラメータを読み込む
uwsgi_pass unix:///path/to/yourapp.sock; # uWSGIに転送するソケットパス
}
}
-
server_name
- このサーバブロックがどのドメインまたは IP を扱うか指定します。
-
location /
- ルートパス(
"/"
)へのアクセスをどう処理するか定義します。
- ルートパス(
-
include uwsgi_params;
- uWSGI のデフォルトパラメータをインクルードしています。HTTPヘッダなど必要な情報を uWSGI に渡すために使います。
-
uwsgi_pass unix:///path/to/yourapp.sock;
- uWSGI によって作成される Unix ソケットファイル(あるいは TCP ソケット)を指定します。ここでは例として Unix ソケットを使用しています。
Unix ソケット vs TCP ソケット
-
Unix ソケット(
unix:///path/to/yourapp.sock
)- 同じサーバ内で Nginx と uWSGI をやり取りする場合によく使われます。ファイルパスの指定になるのでパーミッション設定に注意が必要です。
-
TCP ソケット(
127.0.0.1:8000
など)- 複数サーバ間で通信する場合などに使われます。
2. uWSGI の設定
uWSGI での Flask アプリ結合
Nginx から渡されたリクエストを受け取るのが uWSGI です。uWSGI は WSGI (Python 用ウェブサーバゲートウェイインタフェース) を実装しており、Flask などの WSGI アプリケーションを動かせます。
uWSGI の設定は、以下のような ini
ファイルや yaml
ファイルなどで行われることが多いです。例えば uwsgi.ini
という名前で用意したとします。
[uwsgi]
# Flaskアプリをロードするためのモジュール(エントリーポイント)
module = wsgi:app
# masterプロセスを使うかどうか
master = true
# ワーカープロセス数
processes = 5
# Unixソケットで待ち受ける場合
socket = /path/to/yourapp.sock
chmod-socket = 660
# プロセス終了時などにソケットを消す
vacuum = true
# masterプロセス終了時にきれいに停止する
die-on-term = true
-
module = wsgi:app
- ここで指定している「
wsgi:app
」は、「wsgi.py
というファイルの中にあるapp
という名前の WSGI アプリケーション」を意味しています。 - 例えば Flask の場合、
wsgi.py
の中でapp = Flask(__name__)
のように定義したものを指すことが多いです。
- ここで指定している「
-
socket = /path/to/yourapp.sock
- 上述の Nginx 設定で指定したソケットパスと一致させます。
-
chmod-socket = 660
- ソケットファイルのパーミッションです。Nginx から読み書きができるようにする必要があります。
wsgi.py (あるいは main.py など)
Flask アプリを uWSGI や Gunicorn といった WSGIサーバから読み込ませるために、エントリーポイントが必要になります。典型的には wsgi.py
というファイルを用意し、そこに Flask アプリを作成するコードを書きます。
# wsgi.py
from myapp import create_app # 自分のFlaskアプリのファクトリ関数をインポートする場合など
# あるいは from flask import Flask; app = Flask(__name__)
app = create_app() # Flaskアプリケーションを初期化
ここで定義された app
という変数が、先述の module = wsgi:app
の app
に対応します。
※ もしシンプルに app.py
の中で app = Flask(__name__)
と定義しているなら、
module = app:app
のように書くことも可能です。
3. Flask アプリケーション自体 (Python コード)
Flask アプリは、典型的には以下のような構成をとることが多いです。
myapp/
├── __init__.py
├── app.py # Flaskのエントリーポイントになるファイル(または wsgi.py)
├── views.py # ルーティングの定義など
├── ...
└── uwsgi.ini # uWSGIの設定ファイル
ルーティング例
# views.py
from flask import Blueprint, request, jsonify
bp = Blueprint('main', __name__)
@bp.route('/')
def index():
return "Hello, world!"
@bp.route('/api/data', methods=['GET'])
def get_data():
# 何か処理
return jsonify({"message": "some data"})
アプリ本体
# app.py (または __init__.py)
from flask import Flask
from .views import bp as main_bp
def create_app():
app = Flask(__name__)
# Blueprint を登録
app.register_blueprint(main_bp)
# もしDB接続や拡張機能の初期化などがあればここで
# ...
return app
こういった形でFlask アプリが定義されます。
uWSGI は、create_app()
で生成された Flask アプリ (ここでは app
) を読み取り、WSGI 経由でリクエストを捌きます。
接続まとめ
-
ブラウザ -> Nginx
- ブラウザ(クライアント)は
http://example.com
にアクセスする。 - Nginx はポート 80(または443)で受け取り、サーバブロックの
location /
の設定に基づき次へ転送。
- ブラウザ(クライアント)は
-
Nginx -> uWSGI
-
uwsgi_pass unix:///path/to/yourapp.sock
で受け取ったリクエストを uWSGI へ渡す。 -
uwsgi_params
に書かれた HTTPヘッダなどの情報を含めて転送。
-
-
uWSGI -> Flask
-
uwsgi.ini
などに設定されたmodule = wsgi:app
を元に、wsgi.py
に定義されたapp
(Flask インスタンス) を WSGI 経由で呼び出す。 - Flask が該当ルート(エンドポイント)を解決し、レスポンスを生成して返す。
-
実際のファイル・エンドポイントまとめ
-
Nginx 設定ファイル
-
/etc/nginx/conf.d/myapp.conf
または/etc/nginx/sites-enabled/myapp.conf
など server { ... location / { uwsgi_pass ... } }
-
-
uWSGI 設定ファイル
-
uwsgi.ini
など module = wsgi:app
socket = /path/to/yourapp.sock
-
-
Flask エントリーポイント (wsgi.py など)
-
app = Flask(__name__)
が定義されている、もしくはファクトリ関数から返す。 - uWSGI がここを読み込んで Flask アプリを呼び出す。
-
-
Flask 内部のルーティング (views.py など)
-
@app.route('/')
のように書いてある部分 - ブラウザから
http://example.com/
やhttp://example.com/api/data
などにアクセスすると実際に呼び出される関数
-
まとめ
-
Nginx は HTTP リクエストを受け付け、
uwsgi_pass
で uWSGI に転送。 -
uWSGI は WSGI インタフェースを通じて Flask の
app
を呼び出す。 - Flask で定義されたルート(エンドポイント)が処理を行い、レスポンスを作ってブラウザへ返す。