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/

公式ドキュメントによると上のようなものだそう。

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とか仮想環境ってなんだよ?という方は以下の記事を参考にしてください。
【Ubuntu】Pythonの仮想環境を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()

上記で記述している内容に関しては以下のページで詳しく解説しているので、
分からない箇所があったら見てみて。
FlaskでHello Worldする方法を超丁寧に解説してみる。

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アドレスを指定することが出来、
省略された場合にはlocalhostが対象となる。

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

本当は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ファイルとして保存することで、
簡単に実行させることが出来るようになる。
そのiniファイルの書き方については以下。

uWSGI

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出力までの流れの解説は終了。

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

参考サイト