TOP

    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
    

    Written by addshlab