stylesheet

2024-08-17

Flaskアプリケーションをサブディレクトリで公開

Flaskで作成したアプリケーションをサブディレクトリにマウントして公開する方法。 Flaskの機能ではないのでドキュメントを見ていてもなかなか見つけにくいが、WSGIミドルウェアを使用するものが正解。

毎回調べている気がするのでメモしておく。

設定内容

以下のように、http://localhost/consoleで公開する。

# nginx config

upstream console {
  server 127.0.0.1:8110;
}

server {
  ...

  location /console {
    proxy_pass http://console;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

  ...
}

このままではurl_for等のurl生成が壊れるので、 APPLICATION_ROOTを設定してやり、WSGIのミドルウェアを挟んでやるとうまく動作する。 環境変数を参照するようにすると、開発環境等にもコード修正なしで対応できる。

# app.py

import os
from flask import Flask, request, url_for, render_template
from werkzeug.serving import run_simple
from werkzeug.middleware.dispatcher import DispatcherMiddleware

application = Flask(__name__)

application_root = os.environ.get('FLASK_APPLICATION_ROOT', '')
application.config['APPLICATION_ROOT'] = application_root

application.wsgi_app = DispatcherMiddleware(run_simple, {application_root: application.wsgi_app})


@application.route('/')
def index():
    urls = (
        url_for('index', _external=True),
        url_for('index'),
        url_for('static', filename='css/style.css'))
    return '<br>'.join(urls)


if __name__ == "__main__":
    application.run(host=0.0.0.0)

今回は、WSGIコンテナにNGINX Unitを使用してみた。 インストール方法は割愛。

# config.json

{
    "listeners": {
        "*:8110": {
            "pass": "applications/console"
        }
    },
    "applications": {
        "console": {
            "type": "python",
            "user": "yamori",
            "group": "yamori",
            "working_directory": "/home/yamori/workspace/console/",
            "path": "/home/yamori/workspace/console/",
            "home": "/home/yamori/.anyenv/envs/pyenv/versions/console",
            "module": "app",
            "environment": {
                "FLASK_APPLICATION_ROOT": "/console"
            }
        }
    }
}

ソケットにputして反映させる。

$ sudo curl -X PUT --data-binary @config.json --unix-socket /run/control.unit.sock http://localhost/config/

以上で、webサーバー経由でのアクセスhttp://localhost/console、pythonファイルの直接実行時のhttp://localhost:5000どちらの場合でも正しいパスが生成される。