Flask, uWSGI, nginxでHello Worldする方法を超丁寧に解説

2019年8月12日

この記事では、上の画像のようにFlask, uWSGI, Nginxを連携させてHello Worldさせる方法を丁寧に解説します。

著者環境

OS: Ubuntu 18.04.2 LTS
python: python 3.6.8

コンポーネント説明

Flask, uWSGI, nginxの役割について説明します。

Flaskとは

Python用のマイクロWeb開発フレームワーク

https://a2c.bitbucket.io/flask/

flaskはPythonを使ったWebアプリケーションの作成を
簡単に出来るようにしてくれる枠組み(スケルトン)って考えればOKです。

nginxとは

Webサーバーの一つです。読み方は「エンジンエックス」。
Webサーバーの役割はクライアント(Webブラウザ)からの要求に対して、
要求にあったファイルを渡してあげること。

Webサーバーにはいくつか種類があるけど、
nginxはその中でもサーバーの負荷分散機能に優れていて、
大量アクセスを処理できるように設計されています。

PCの使用者数は年々増えてきているので、
大量アクセスに対応出来るnginxは人気が上がってきています。

uWSGIとは

uWSGIの説明に入る前にWSGIの説明からします。

WSGIは”Web Server Gateway Interface“の略称です。
公式サイトには以下のように説明がされています。

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

https://www.python.org/dev/peps/pep-0333/

つまり、”WebサーバーとPythonで書かれたアプリケーションをつなぎ合わせてくれるもの” 。

この機能を果たすWSGIサーバーの一つがuWSGI。
今回の構成の中ではFlaskとnginxを結びつける働きをしてくれます。

またuWSGIはFlaskを稼働させるアプリケーションサーバーでもあります。

完成図

上記のことを踏まえて以下のような構成でHello Worldを出力します。

図でuWSGIとFlaskが近いのはuWSGIがFlaskを稼働させるアプリケーションサーバーであることを示すためです。

インストール

ここから先はvenvで作った仮想環境の中で操作をしていきます。
venvとか仮想環境ってなんだよ?という方は以下の記事を参考にしてください。

uWSGI

## uWSGIのインストール
# uwsgiのインストールに必要なものをインストール
$ sudo apt install python3-dev
$ pip install wheel
# uwsgiのインストール
$ pip install uwsgi

Nginx

# nginxをaptで管理できるようにする(nginx.listの作成)
$ sudo sh -c 'echo "deb http://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx" > /etc/apt/sources.list.d/nginx.list'
$ sudo sh -c 'echo "deb-src http://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx" >> /etc/apt/sources.list.d/nginx.list'
# おそらくエラーになるけど確認したい内容があるのでapt update
$ sudo apt update
# the public key is not available: NO_PUBKEY ???というエラーが出ると思うので???部分をコピー
# 正式なnginxをinstallするための公開鍵ダウンロード
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ???の文字列
# あとは普通に
$ sudo apt update
$ sudo apt install nginx

Flask

## Flaskのインストール
$ pip install flask

実装

それではこれからコーディング作業に入ります。

以下のディレクトリ構成のファイルを作ります。
作る場所はどこでもOK。ディレクトリ名に付いているNUFはnginx,uWSGI,Flaskの略です。

NUF_hello
   ├── main.py  # Flaskのファイル
   └── uwsgi.ini  # uWSGIの設定ファイル

Flask

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
    return "Hello World!"
if __name__ == "__main__":
    app.run()

上記で記述している内容に関しては以下のページで詳しく解説しているので、
何をしているのか分からない箇所があったら見てください。

nginx

nginxの設定ファイルを編集します。
設定ファイルは/etc/nginx/nginx.confにあります。

ただし今回編集するのはここではありません。
nginx.conf内には「include /etc/nginx/conf.d/*.conf;」という記述があり、
/etc/nginx/conf.dディレクトリ配下にあるconf拡張子のファイルを読み込み、
そのファイルに記述されている内容も nginxの設定として反映されます。

そこで今回は「/etc/nginx/conf.d/uwsgi.conf」というuWSGIとの連携用ファイルを作成します。

server {
    listen       50000;
    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
}

server { ~ }

波括弧内に記載されたlisten(後述)やserver_nameで指定されたサーバーに対する設定を記載するブロック

listen

listenの後にある数字がこの設定と対応するポート番号です。
172.16.0.39:80のようにIPアドレスを指定することが出来、
IPアドレスが省略された場合にはlocalhostが対象となります。

今回の場合はlocalhostのポート番号50000にアクセスがきた時に
locationブロック内の設定にしたがって情報の処理がされます。

本当はwebサーバーの場合80番ポートを使いたいところですが、
すでに存在する/etc/nginx/conf.d/default.confファイル内で
80番ポートを対象とした設定がされているため、あえて50000番ポートにしています。
参考URL:Webサーバは80番ポート以外使ってはいけないの?

location

locationはリクエストで送られてきたパスに対応して、
nginxがどこに情報を受継げば良いのかを示している。

「location / {」の意味は「/で始まるpathがきた時にはブロック内の処理をする」。
全てのパスは/で始まるので、他にもっと詳細なlocationの設定をしている箇所がなければ、
この箇所で処理することになります。

locationについてもっと詳しく知りたい方には以下のサイトがおすすめ。
nginx連載5回目: nginxの設定、その3 – locationディレクティブ

50000番ポートにきた時の設定をしているuwsgi.confには
この一つのlocationしか存在しないため、
全ての処理をこのlocationの設定に従って行うことになります。

include uwsgi_params;

uwsgi_paramsというファイルを読み込んで、
このファイルに記述されている設定を利用出来るようにしています。

uwsgi_paramsというファイルはnginxのインストールと同時に作られ、
nginxとflaskを連携を行うために必要な色々な設定が書かれています。

uwsgi_pass unix:///tmp/uwsgi.sock;

uwsgiへの接続窓口を指定しています。

この記載によって、50000番ポートにアクセスがきた時には、
localhostの/tmp/uwsgi.sock(ソケット,情報の窓口)に処理を引き継ぐことにります。

スラッシュが3つに付いているのはローカルホストに対するアクセスを表しています。

参考URL : 「file:///」でスラッシュが3つ並んでいる理由

実行

ここまでの設定を全て行い、以下の手順を踏んでから、
127.0.0.1:50000にwebからアクセスすればHello Worldが出力されます。
(オプションの解説は後述)

# nginxを再起動させ、編集したファイルを読み込ませる。
$ sudo systemctl restart nginx
# uWSGIの起動
$ uwsgi --socket /tmp/uwsgi.sock --module main --callable app --chmod-socket=666

ただしuWSGIを起動する際、毎回オプションを付けまくってコマンド実行するのは面倒です。

そこで朗報。

今回コマンドでオプションを書いていた部分をiniファイルとして保存することで、
簡単に実行させることが出来るようになります。

uwsgi.ini

uwsgiのiniファイルは以下のように書く。

[uwsgi]
socket = /tmp/uwsgi.sock
module = main
callable = app
chmod-socket = 666
  • socket
    利用するnginxからの情報の受け渡しの窓口となるソケットファイルを指定。
  • module
    実行するファイルを示す。
    今回Flaskアプリケーションを作成しているのはmain.pyなのでmainと指定
  • callable
    作成されるFlaskアプリケーションの名称を指定。
    今回main.py内で「app = Flask(__name__)」と記述して、
    アプリケーションを作成していたので、アプリケーション名はapp
  • chmod-socket
    nginx側がソケットファイルに対して読み込み書き込みが出来るように権限を変更
    (ソケットもファイルです)

以下のコマンドを実行することで、iniファイルを読み込んでuwsgiを起動することが出来ます。

$ uwsgi --ini uwsgi.ini

上記のコマンドを実行した状態で127.0.0.1:50000にwebからアクセスすればHello Worldが出力されます。

まとめ

以上でuWSGIとFlaskとnginxを連携させたHello World出力までの流れの解説は終了です。

なぜこれで動くのか、またなぜこのような構成にする必要があるのか、
最初から記事を読み直して復習をしてもらえると嬉しいです。

長い記事でしたが、読んでくださりありがとうございました。

参考サイト