Python
nginx
Flask
uwsgi

写経「nginx + uwsgi でアプリケーションをサブディレクトリで動かす設定」

nginx + uwsgi でアプリケーションをサブディレクトリで動かす設定 - Qiitaの写経

/にアクセスが来たら/abortにリダイレクトする簡単なWebアプリケーションを作ったとする。
一つのサーバーの/を占有するのは勿体無いのでディレクトリを切ってその下で動かしたい。

再配置可能プログラム(リロケータブル)なものにしたいのでアプリ側は上位パスをハードコードしないようにする。

app.py
from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route('/')
def index():
    return redirect(url_for('about'))

@app.route('/about')
def about():
    return 'The about page'

if __name__ == '__main__':
    app.run()
subdir.ini
[uwsgi]
module = app:app
callable = app
home = %v/venv
socket = /var/run/uwsgi/subdir.sock
chmod-socket = 666
http-socket = :5000 # これはデバッグ用
/etc/nginx/default.d/subdir.conf
location ~ ^/subdir/(.*)$ {
        include uwsgi_params;
        uwsgi_pass unix:/var/run/uwsgi/subdir.sock;
        uwsgi_param SCRIPT_NAME /subdir;
        uwsgi_param PATH_INFO /$1;
}
// これは管理者で
# mkdir -m 777/var/run/uwsgi

// ここからは一般ユーザーで
$ python36 -m venv venv
$ source venv/bin/activate
$ pip install flask uwsgi
$ uwsgi --ini subdir.ini

// リクエストすると生きている
$ curl localhost:5000 -I
HTTP/1.1 302 FOUND
Content-Type: text/html; charset=utf-8
Content-Length: 219
Location: http://localhost:5000/about

// nginxの設定によってルーティングが効いている
$ curl localhost/subdir/ -I
HTTP/1.1 302 FOUND
Content-Type: text/html; charset=utf-8
Content-Length: 233
Connection: keep-alive
Location: http://localhost/subdir/about // subdir以下にリダイレクトされる

追加

layout.html
当然ながら、パスが変わるのでcssやjsのパスはjinja2でurl_for()を使っておく方がよい。
具体的には

<script src="/static/js/bootstrap.min.js"></script>
ではなく
<script src="{{url_for('static', filename='js/bootstrap.min.js')}}"></script>
としておかないと追従しない

参考

メモ帳 | DockerizedしたFlaskをサブディレクトリで運用する
コードでやる方法。nginx側とflask側両方の小細工が必要。

アプリケーションの発送 - Flask 1.0.2ドキュメント
Dispatch by Pathがそれらしいが使い方がわからなかった

djangoとuwsgiとnginxを使って、複数のアプリを公開する時の話 - Qiita

flask_script_name.md

nginx + uwsgi + flask の連携でつまずく - 達人ドヤリストへの道
この人と同じところでつまづいた。Blueprintという手もあるがpythonだけのアプリとは限らないのでnginxでやるのがよさげ

Nginx support — uWSGI 2.0 documentation

Nginx+uwsgi+Bottle.pyで環境変数を使いたい|ご注文はスタートアップですか?
これを使えばサブディレクトリパスがアプリ側で取れそう

Mounting flask under subpath through nginx · Issue #527 · zalando/connexion
みんな同じ悩みを持つ