Amazon Linux に python3 + Flask + uWSGI + nginx を導入し、本番運用に耐えるウェブサーバを構築

  • 33
    Like
  • 0
    Comment
More than 1 year has passed since last update.

この記事は
「AWS EC2 に Python の演算結果を Json で出力する API サーバを10分で構築」
http://qiita.com/kent_ocean/items/12e44ea4456c1e869bad
の続きです。

前回の記事で Flask を使った APIサーバ を構築したわけですが、Flask の Run メソッドはあくまでも開発用サーバとして使うもので、本番環境には適しません。

今回は、Flask に uWSGI と nginx を組み合わせ、nginx からリバースプロキシして uWSGI で Flask アプリを動かす構成にして、本番での運用に耐えるサーバを作ろうと思います。

あと、どうでもいいことですが、とりあえず僕はこの構成を LNUP と勝手に命名することにしました。(LNUP = Linux + nginx + uWSGI + python)
(他の呼び方がありましたら教えてください)

前提条件

今回の記事は以下の環境で手順を検証しています。

Version
OS Amazon Linux AMI 2016.03.3 (ami-374db956)
Python 3.5.2
Flask 0.11.1

導入するソフトウェアのバージョン

今回の記事で実際にインストールしたソフトウェアのバージョンは以下の通り

Version
uWSGI 2.0.13.1
nginx 1.11.1

uWSGIのインストールと設定

インストール

pip install uwsgi

設定ファイルの作成

flask の py ファイルと同じ階層に設定ファイルを作成します。

cd /var/www/flask
sudo vim uwsgi.ini
uwsgi.ini
[uwsgi]
#application's base folder
base = /var/www/flask

#python module to import
app = hello_world
module = %(app)

#socket file's location
socket = /var/www/flask/tmp/uwsgi.sock
#socket = /tmp/uwsgi.sock

#permissions for the socket file
chmod-socket = 666

#the variable that holds a flask application inside the module imported at line #6
callable = app

#location of log files
logto = /var/log/uwsgi/%n.log

master = true
processes = 1
vacuum = true
die-on-term = true

log を入れるディレクトリを作成

sudo mkdir -p /var/log/uwsgi
sudo chmod o+w /var/log/uwsgi

テストコードを作成

sudo vim hello_world.py
hello_world.py
from flask import Flask
app = Flask(__name__)

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

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

※ Flask 公式にある Hello World をそのまま転載
http://a2c.bitbucket.org/flask/quickstart.html

※ runメソッドに IPアドレスやポート番号、スレッド処理フラグなどの引数を付ける必要はありません。

Nginx1.11をインストール

Amazon Linux 標準のリポジトリからインストールすると Nginx 1.8 になってしまうので、nginx のリポジトリを参照するよう変更します。

sudo rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
sudo vim /etc/yum.repos.d/nginx.repo
nginx.repo
name=nginx repo
-baseurl=http://nginx.org/packages/centos/6/$basearch/
+baseurl=http://nginx.org/packages/mainline/centos/6/$basearch/
gpgcheck=0
enabled=1
+priority=1

Nginx のバージョンを確認

sudo yum install nginx
nginx -v
nginx version: nginx/1.11.1

sites-available と sites-enabled の作成

site-available ディレクトリに設定ファイルを置いておき、必要な設定だけをシンボリックリンクで sites-enabled に置く構成にします。

sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabled

Nginx 設定ファイルを作成

sudo vim /etc/nginx/sites-available/uwsgi.conf
uwsgi.conf
server {
  listen 80;
  error_log  /var/log/nginx/error.log warn;

  location / {
    include uwsgi_params;
    #uwsgi_pass unix:///tmp/uwsgi.sock;
    uwsgi_pass unix:///var/www/flask/tmp/uwsgi.sock;
  }
}
sudo vim /etc/nginx/nginx.conf

nginx の設定ファイルに sites-enabled を含む記述を追加

nginx.conf
#include /etc/nginx/conf.d/*.conf;
+ include /etc/nginx/sites-enabled/*;

※こう書けば nginx は default.conf を読まずに uwsgi.conf の設定だけを読み込むようになります。

シンボリックリンクを作成

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

設定が正しいかどうか確認

sudo service nginx configtest

nginx の設定を再読込

sudo service nginx reload

権限設定

uWSGI の実行ユーザーが /var/www/flask/tmp に socket を作成できるよう権限を設定します。

sudo chmod o+w /var/www/flask/tmp

nginxが /var/www/flask/tmp の socket にアクセスできるよう権限を設定します。

sudo chown nginx:nginx /var/www/flask/tmp

uWSGI を起動

cd /var/www/flask
uwsgi --ini uwsgi.ini

ブラウザからアクセス

http://(IP Address):80

ブラウザに「Hello world!」と表示されれば成功です。

補足

今回の手順では、uWSGI の socket ファイルが /var/www/flask/tmp ディレクトリ下に生成される設定で進めてみました。
ネットでぐぐると /tmp 直下にしている方が多いようなんですが、本当にここで良いのかなという疑問があったので。。。

で、この設定で進めていくと

↓こんなエラーや

connect() to unix:////var/www/flask/tmp/uwsgi.sock failed (2: No such file or directory) while connecting to upstream,

↓こんなエラー

invalid host in upstream "/var/www/flask/tmp/uwsgi.sock"

が出まくって結構苦労しました。

まあ、結局ほとんど権限設定に起因する問題なので

  1. uWSGI の実行ユーザーが、指定ディレクトリに socket ファイルを書き込む権限の有無
  2. nginx が、socket ファイルが生成されているディレクトリにアクセスする権限の有無

の2点に注意して、nginx と uWSGI のエラーログを見ていけば何とかなるんですが。
もうちょっと良い運用方法があるような気がしますが、、、今後の検討課題かなー。

以上です。