2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Raspberry Pi 3 Model B+にNginxとuWSGIを使ってFlaskを動かしてみた

Posted at

背景・目的

Pythonで実装したアプリケーションを本番環境にデプロイする際にuWSGIを用いるのは知っていたが、なぜ使うのかや使い方について知らなかった。そこで、NginxとuWSGIとPython + Flaskを用いてRaspberry Pi 3 Model B+で動かしてみる。

そもそもWSGIとはWeb Server Gateway Interfaceの略である。PEP 3333のAbstructに記載されているようにウェブサーバーとPythonアプリケーションを繋ぐインターフェースのことで、様々なWebサーバ間でWebアプリケーションの移植性を高めるものである。

This document specifies a proposed standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers.

このWSGIに即したWSGIアプリケーションコンテナのuWSGIを用いてPython + Flaskで作成したアプリケーションをデプロイする。

実装

実装した順序は以下である。

  1. 開発環境でFlaskのアプリケーションを動かす
  2. uWSGIでFlaskのアプリケーションを動かす
  3. Nginxの設定をしてブラウザからラズパイのIPを叩く
  4. uWSGIを自動起動化させる

開発環境でFlaskのアプリケーションを動かす

まず、開発環境のディレクトリは以下のようになっている。

$ tree
.
├── README.md
├── conf
│   └── uwsgi.ini
├── requirements.txt
└── src
    └── main.py

requirements.txtに必要なライブラリを記載している。これを用いて pip install -r requirements.txt でライブラリをインストールできる。

$ cat requirements.txt 
flask
isort
flake8
ipython
uwsgi

src/main.py は以下である。

$ cat src/main.py 
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World!'

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

python src/main.py で開発用サーバーが5000番ポートで起動し、アプリケーションが実際に動いていることがわかる。

uWSGIでFlaskのアプリケーションを動かす

実際にアプリケーションを運用する際には、様々な設定をする必要がある。例えば、ソケットの出力先やプロセス数やスレッド数などが挙げられる。これらの設定をuwsgiコマンドのオプションに連ねて指定するのは面倒なので、以下のuwsgi.iniファイルにオプションをまとめる。

そうすると、uwsgi --ini uwsgi.ini でアプリケーションが実際に動いているかを確認することができる。

$ cat conf/uwsgi.ini
[uwsgi]
wsgi-file = ../src/main.py
; module = main
callable = app
chmod-socket = 666
socket = /tmp/%n.sock
;http = 0.0.0.0:8080
;daemonize = /var/log/uwsgi/flask/%n.log
;pidfile = /tmp/app.pid
;harakiri = 600

Nginxの設定をしてブラウザからラズパイのIPを叩く

Nginx の80番ポートにHTTPリクエストでアクセスした後、UNIXドメインソケットを利用してuWSGIにプロキシを行う。そのNginx側の設定が以下になる。

server {
    listen 80;
    # 80番ポートにアクセスするとFlaskのアプリにリバースプロキシする
    # この方法だとポートを無駄に使わずに済む
    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
    proxy_set_header  Host                $host;
    proxy_set_header  X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Host    $host;
    proxy_http_version      1.1;
    proxy_connect_timeout 600;
    proxy_read_timeout    600;
    proxy_send_timeout    600;
    send_timeout          600;
    uwsgi_read_timeout    600;
}

ちなみに、UNIXドメインソケットとは、同一マシン上で動いているプロセス間通信を行うためのソケットのことである。従って、他のマシンと通信することはできない。一方で、IPとポート番号を頼りにネットワークを介して他マシンと通信するソケットは、INETドメインソケットと呼ばれる。UNIXドメインソケットは同一マシン上のプロセスとしか通信することができないが、INETドメインソケットと比較すると高速である。

uWSGIを自動起動化させる

uWSGIをdaemon化する方法はいくつか挙げられる。1つ目は、uwsgiコマンドのオプションにdaemonizeのオプションを付けることである。2つ目は、systemctlにuWSGIを登録して自動起動化させる方法である。今回の実装では2つ目を採用した。

  • サービス(/etc/systemd/system/app.service) の作成
[Unit]
Description=uWSGI instance to serve myapp
After=network.target

[Service]
;User==www-data
Group=www-data
WorkingDirectory=/home/pi/WorkSpace/DeployFlask/conf
ExecStart=/home/pi/.pyenv/shims/uwsgi --ini /home/pi/WorkSpace/DeployFlask/conf/uwsgi.ini

[Install]
WantedBy=multi-user.target
  • サービスの起動
$ sudo systemctl start app
  • サービスの自動起動の設定
$ sudo systemctl enable app
  • サービスの状況把握
$ sudo systemctl status app
● app.service - uWSGI instance to serve myapp
   Loaded: loaded (/etc/systemd/system/app.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-05-12 18:22:25 JST; 7min ago
 Main PID: 2615 (uwsgi)
    Tasks: 1 (limit: 2200)
   Memory: 10.9M
   CGroup: /system.slice/app.service
           └─2615 /home/pi/.pyenv/versions/DeployFlask/bin/uwsgi --ini /home/pi/WorkSpace/DeployFlask/conf/uwsgi.ini

詰まったこと・課題

  • uwsgi.iniファイルに daemonize = /var/log/uwsgi/flask/%n.log を記述していたので、一定時間後にサーバーが502を返す自体が生じた。uwsgiをdaemon化させるために取った1つ目の方法だったが、その記述が悪さをしていたので削除した。

参考

Deploy

記事

Socket通信

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?