7839

雑草魂エンジニアブログ

【Python】Flaskの本番環境構築(Flask + uWSGI + Nginx)

前回の記事で、PythonのWebアプリケーションフレームワークであるFlaskHello Worldをローカル開発環境で確認するまでを紹介した。

serip39.hatenablog.com

今回、Raspberry Pi 3 Model B 上にWebサーバーを構築して、FlaskのWebアプリケーションを本番環境に公開するまでを紹介する。

Flaskの本番環境に関して

This launches a very simple builtin server, which is good enough for testing but probably not what you want to use in production. Flask公式

Flaskには組み込みサーバーがあり、特別な環境構築を行うことなく、Webサーバーを立ち上げることができる。ただし、この組み込みサーバーを本番環境でも使用することは推奨されていない。

そこで、通常のWebサーバーであるApacheやNginxを用いて、FlaskのWebアプリケーションを公開する。Flaskは、WebサーバとアプリケーションをつなぐインターフェースであるWerkzeugを基にしており、WSGI(Web Server Gateway Interface)に準拠してWebサーバーと通信することができる。そのため、今回の本番環境は、このような構成図になる。

f:id:serip39:20200705232240p:plain

FlaskはWSGI(Web Server Gateway Interface) を用いているため、直接ApacheやNginxのWebサーバーと通信することができない。そのため、「uWSGI」を使うことが通例になっている。

uwsgi-docs.readthedocs.io

uWSGIとNginx間の通信は、高速で安定した通信が可能な「Socket」を用いた。

環境構築

ゼロから環境構築を順番に行っていく。

  1. Pipenvで仮想環境構築する
  2. uWSGIの動作確認をする
  3. Flaskの組み込みサーバーでHelloWorldを表示する
  4. uWSGIを通してFlaskのサイトをブラウザに表示する
  5. Nginxの動作確認をする
  6. Nginxのバーチャルホストの設定を行う
  7. uWSGIの設定ファイルを作成する
  8. NginxとuWSGIを接続して、動作確認をする
  9. 自動起動を設定する

1. Pipenvで仮想環境構築する

まずは、仮想環境にFlaskとuWSGIをインストールする。

$ pip3 install --upgrade pip    # pipを最新版にアップグレードする
$ pip3 install pipenv    # pipenvをインストールする
$ export PATH=$PATH:/home/pi/.local/bin  # PATHを追加する

$ mkdir ./flask-test    # flask-testディレクトリを作成
$ cd ./flask-test    # flask-testディレクトリに移動
$ pipenv install --python 3.7.3  #3.7.3で仮想環境構築

$ pipenv install uwsgi    # 仮想環境にuwsgiをインストール
$ pipenv install flask    # 仮想環境にflaskをインストール
$ pipenv shell #仮想環境を実行

2. uWSGIの動作確認をする

flask-testディレクトリ直下に、test.pyを作成してください。

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World uWSGI"]

次に、以下のコマンドでuWSGIを起動する。

(flask-test)pi$ uwsgi --http :8000 --wsgi-file test.py
オプション 概要
--http:8000 ポート8000を使用して、HTTPプロトコル通信をする。
--wsgi-file test.py WSGIサーバーでtest.pyを実行する。

http://127.0.0.1:8000 にアクセスして、「Hello World uWSGI」が表示されていれば、ブラウザがuWSGIを通してPythonのプログラム(test.py)にアクセスできた事を意味する。

3. Flaskの組み込みサーバーでHelloWorldを表示する

次に、Flaskの組み込みサーバーでFlaskのサイトが実行できるか動作確認を行う。 flask-testのディレクトリ直下に、app.pyを作成してください。

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello world Flask"

if __name__ == "__main__":
    app.run()

以下のコマンドで、Flaskの組み込みサーバーを起動してください。

(flask-test)pi$ python app.py

http://127.0.0.1:5000にアクセスして、「Hello World Flask」が表示されていれば、ブラウザを通して、HTTP通信でFlaskの組み込みサーバーにアクセスできた事を意味する。

4. uWSGIを通してFlaskのサイトをブラウザに表示する

以下のコマンドを実行してください。

(flask-test)pi$ uwsgi --http :8000 --wsgi-file app.py --callable app

http://127.0.0.1:8000にアクセスして、「Hello World Flask」が表示されていれば、uWSGIを通してFlaskのサイトをブラウザに表示することができたことになる。

5. Nginxの動作確認をする

一度、仮想環境からログアウトして、Nginxをインストールする。

(flask-test) pi $exit    #exitして仮想環境から出る
pi$ sudo apt install nginx
pi$ sudo /etc/init.d/nginx start 
[ ok ] Starting nginx (via systemctl): nginx.service.

起動が成功したら http://127.0.0.1:80 にアクセスする。 正常に動作していた場合、「Welcome to nginx!」のページが表示され、ブラウザとWebサーバの連携が確認できる。

6. Nginxのバーチャルホストの設定を行う

NginxでuWSGIを介して、FlaskのWebアプリケーションを公開するための設定を行う。

# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

nginx.confの設定ファイルには、上記のような記載があり、以下の2つのフォルダを参照している。

  • /etc/nginx/conf.d : 既存のファイルなし
  • /etc/nginx/sites-enabled/ : defaultのファイルのみ

/etc/nginx/sites-enabled/defaultに基本設定が記載されている。バーチャルホストに関しては、以下の記載がある。

# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.

sites-availableに設定ファイル実体を配置して、sites-enabledに設定ファイルへのシンボリックリンクを張るのが通例のようだ。

sites-available、sites-enabledのフォルダ直下には、同じdefaultファイルが存在する。コピーを作成して、ファイル名を変更する。

$ cd /etc/nginx/sites-available
$ sudo cp default ./app_nginx.conf

defaultファイルを編集しても問題ないが、ほとんどの設定を削除して、以下のような設定ファイルとしてください。/var/www/に80番ポートでアクセスしたときに、uWSGIに接続するような設定にする。

# Virtual Host configuration for example.com
server {
        listen 80;
        server_name example.com;        
        location / {
          include uwsgi_params;
          uwsgi_pass unix:/tmp/uwsgi.sock;
        }
}

uwsgi.sockはソケットファイルであり、勝手に作られるので特に用意しておく必要はない。NginxはuWSGIに接続する際に、UNIXソケットを間に噛ませて通信する。これにより、ポート番号を消費せずに済む。

シンボリックリンクを設定する。

$  cd /etc/nginx/sites-enabled/
$  sudo ln -s /etc/nginx/sites-available/app_nginx.conf app_nginx.conf

最後に、/etc/nginx/sites-enabled/にはdefaultファイルが存在するので、.confファイルのみが有効になるようetc/nginx/nginx.confを編集する。

# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;  #ここを編集する

7. uWSGIの設定ファイルを作成する

flask-testフォルダ直下に、myapp.iniを作成し、uWSGIの設定を行う。

flask-test
 |- app.py
 |- test.py
 |- myapp.ini
[uwsgi]
module = app
callable = app
master = true
processes = 1
socket = /tmp/uwsgi.sock
chmod-socket = 666
vacuum = true
die-on-term = true
chdir = /home/pi/flask-test  # フォルダのディレクトリを指定する

8.NginxとuWSGIを接続して、動作確認をする

uWSGIサーバーを以下のコマンドで立ち上げる。

$ uwsgi --ini myapp.ini

別のターミナルを開いて、nginxを起動する

$ sudo /etc/init.d/nginx start

http://127.0.0.1:80 にアクセスし、「Hello World Flask」を確認することができれば、本番環境の構築ができたことになる。

9. 自動起動を設定する

systemctlを用いて、自動起動できるよう設定を行っておく。 systemctlに登録するために、/etc/systemd/system/内にuwsgi.serviceファイルを作る。

[Unit]
Description = uWSGI
After = syslog.target
[Service]
ExecStart = /home/pi/.local/bin/uwsgi --ini /home/pi/flask-test/myapp.ini #ファイルのパスを指定する
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target

systemctlのコマンドは以下の通りである。

$ systemctl status uwsgi //status確認
$ systemctl start uwsgi // uWSGI開始
$ systemctl stop uwsgi // uWSGI停止
認証を求められるので、Raspberry Piのユーザーパスワードを入力する。

最後に、自動起動の設定を行う。

$ systemctl enable uwsgi

これで、電源再起動をしても、自動で起動するようになった。 Nginxは自動でsystemctl に登録されており、再起動しても自動で立ち上がるようになっていた。

まとめ

今回は、Raspberry Pi上で、Flask + uWSGI + NginxでWebアプリケーションを公開する方法を紹介した。Raspberry Piでなくても、基本的にはLinuxで同様な動作をするはずである。

それでは、ステキな開発ライフを。