Help us understand the problem. What is going on with this article?

Flask + uWSGI + Nginx でハローワールドするまで @ さくらのVPS (CentOS 6.6)

More than 1 year has passed since last update.

前提

Flaskアプリケーションのローカル環境での開発方法は知っていて、本番環境でのdeploymentの方法が知りたい。uWSGIやNginxについてはあまり知らない。

概略

Flaskの公式によると

You can use the builtin server during development, but you should use a full deployment option for production applications.

とのことなので、アプリを公開するには組み込みサーバーの利用はせずに、別の方法を考える必要があるらしい。様々な方法があるようだが、ここではuWSGIとNginxという組合せで進める。

まず、基本的な言葉の整理からおこなう。

uWSGI

uWSGIは、WSGIと名前は似ているが異なる概念であることに注意する。

WSGI(Web Server Gateway Interface)はPEP333において

a simple and universal interface between web servers and web applications or frameworks

と定義される仕様のことであり、ウェブサーバとアプリケーションをつなぐインターフェースの役割を担う。これにより、フレームワークとサーバの実装が一般化され、アプリケーションの移植可能性が高まるなどのメリットがある。

uWSGIは、WSGIアプリケーションとウェブサーバをつなぐサーバを指す。uWSGIは、uWSGI、HTTP、そしてFastCGIなどのプロトコルを用いてウェブサーバと通信する。ここではuwsgiというサーバを利用して、uWSGIプロトコルによりウェブサーバと通信する(言葉が紛らわしいですが、uWSGIは文脈によってサーバを指したりプロトコルを指したりするので注意が必要です)。

以上の関係を図式的に表すと次のようになる。

Framework <-> uWSGI <-> Web Server <-> Client

今回の場合では

Flask <-> uwsgi <-(uWSGI protocol)-> Nginx <-(HTTP)-> Client

となる。

インストール

flaskとuwsgiをpipで入れておく。ここは情報が豊富なので省略。

デモアプリの作成

アプリの構成

myapp
 |-app.py
 |-myapp.ini
 |-venv

app.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

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

myapp.ini

これについては後述する。

[uwsgi]
module = app
callable = app
master = true
processes = 1
socket = /tmp/uwsgi.sock
chmod-socket = 666
vacuum = true
die-on-term = true

Nginxの設定

Nginxの設定ファイルは、大本の設定ファイルは/etc/nginx/nginx.confであり、このファイルの中にinclude /etc/nginx/conf.d/*.confと記述してあることで、さらに下位の/etc/nginx/conf.d/内にある*.confファイルが呼び出される仕組みとなっている。ここでは、アプリケーションを動かすのに必要な最小限の設定ファイルをconf.d/内に置くこととする。

server {
    listen       80;

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

これは、サーバのルートにHTTP(ポート80)でアクセスがあれば、/tmp/uwsgi.sockというソケットに接続するという設定になっている。上述したように、NginxはuWSGIに接続するのだが、ここではUNIXソケットを間に噛ませて通信する。これにより、ポート番号を消費せずに済む。

このことを加味した全体の接続イメージは次のようになる。

Flask <-> uwsgi <-> socket <-> Nginx <-> Client

uWSGIの設定

ここまででapp.pyを任意の場所に設置してNginxの設定を済ませていれば、次のコマンドで一応アクセスすることができる。

$ uwsgi --socket /tmp/uwsgi.sock --module app --callable app --chmod-socket=666

あるいは

$ uwsgi -s /tmp/uwsgi.sock --w app:app --chmod-socket=666

ブラウザからウェブサーバのIPアドレスにアクセスすると、ハローワールドが表示されるはず。上のコマンドの各オプションは次のような意味をもつ。

-s|--socket   接続先のソケットの指定
--module   モジュールの指定
--callable    WSGIにて規定されるcallableオブジェクトの指定
--chmod-socket   ソケットのアクセス権の変更

しかし、上のオプションを毎度打ち込むのも大変なので、uwsgiのための設定ファイルを作成する。それが上述したmyapp.iniとなる。設定ファイルを作成していれば、次のコマンドで同様にuWSGIサーバーが立ち上がる。

$ uwsgi --ini myapp.ini

おわりに

ここまでで、一応FlaskアプリケーションをNginx経由で動かすことはできた。あとは、起動時に自動実行されるよう設定するなどすればOKだろう(そのためには/etc/rc.localをいじればいい)。

参照

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした