Flask+uWSGI+Nginxでサイトを公開する

EC2 などのサーバーに Nginx と uWSGI をインストールして Flask アプリを公開する例です。

テスト環境は CentOS Stream です。

想定するディレクトリ構成

プロセスIDが書き込まれる uwsgi.pid と、ソケット通信用の uwsgi.sock を、プロジェクトのルートに出力しています。これはわかりやすさのためなので、 /run/ (/var/run/) など一般的なプロセス管理用のディレクトリに格納しても構いません。

/var/www/MyProject/
├── DocumentRoot
│   ├── index.html
│   └── static -> ../MyApp/app/static/
├── log
│   ├── nginx/
│   └── uwsgi.log
├── MyApp
│   ├── app/
│   └── venv/
├── uwsgi.ini
├── uwsgi.pid
└── uwsgi.sock

Flaskアプリケーションの登録 (MyProject/MyApp/app/__init__.py)

blueprint を使っています。この辺りはアプリケーションの作り方で差異が出ます。

from flask import Flask

def create_app(test_config=None):
    app = Flask(__name__, instance_relative_config=True)
    from .views.home import home
    app.register_blueprint(home, url_prefix="/")
    return app

if __name__ == '__main__':
    create_app().run(debug=True, use_reloader=True, use_debugger=True)

uWSGI サーバー起動設定 (MyProject/uwsgi.ini)

[uwsgi]
uid = {uwsgiを実行するユーザー}
gid = {uwsgiを実行するグループ}
chdir = /var/www/MyProject/MyApp
module = app:create_app()
master = true
socket = /var/www/MyProject/uwsgi.sock
pidfile = /var/www/MyProject/uwsgi.pid
chmod-socket = 666
vacuum = true
die-on-term = true
logto = /var/www/MyProject/log/uwsgi.log

Nginx設定 (/etc/nginx/conf.d/myproject.conf)

Flask のルーティングに関係する部分を記載します。他は一般的な CMS や HTML の公開と変わりません。ログも別の場所に出力して構いません。

server {
    access_log  /var/www/MyProject/log/nginx/access.log main;
    error_log   /var/www/MyProject/log/nginx/error.log warn;

    root  /var/www/MyProject/DocumentRoot;

    location @uwsgi {
        include uwsgi_params;
        uwsgi_pass unix:/var/www/MyProject/uwsgi.sock;
    }

    location / {
        try_files $uri @uwsgi;
    }
}

uWSGIサービス設定 (/etc/systemd/system/myapp.uwsgi.service)

systemd で uWSGI を起動させるための設定です。この例の場合、最初にアプリケーションルートに入って venv を起動し、必要なモジュールをインポートする準備をしています。

別のアプリケーションのプロセスを登録する場合は、myapp.uwsgi.service の myapp の部分を任意のものに変更します。

[Unit]
Description = uWSGI
After = syslog.target

[Service]
ExecStartPre=/bin/bash -c 'cd /var/www/MyProject/MyApp/; . venv/bin/activate'
ExecStart = uwsgi --ini /var/www/MyProject/uwsgi.ini
Restart=always
Restart=on-failure
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

uWSGI プロセスのコントロール

// 起動
systemctl start myapp.uwsgi.service
// 再起動
systemctl restart myapp.uwsgi.service
// 停止
systemctl stop myapp.uwsgi.service
// ステータス確認
systemctl status myapp.uwsgi.service
// .service は省略可
systemctl start myapp.uwsgi