Python + uWSGI + nginx

# 概要
CentOS 6/7で、Python + uWSGI + nginxの組み合わせでFlaskアプリを動かすまでの試行錯誤。

# 関係パッケージインストール

```sh
# バージョンは環境によって異なるが、ここではPython 3.6とする。
yum install -y python36u python36u-devel python36u-libs python36u-pip

pip3.6 install uwsgi
pip3.6 install flask
```

# アプリ設定

/var/www/アプリディレクトリ/uwsgi.ini

```ini
[uwsgi]
#application's base folder
chdir = /var/www/アプリディレクトリ

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

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

plugin = python36

#socket file's location
socket = /var/run/uwsgi/%n.sock

#permissions for the socket file
chmod-socket = 644 

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

master = true

# maximum number of worker processes
processes = 100 

# clear environment on exit
vacuum = true
```

/var/www/アプリディレクトリ/app.py

```python
from flask import Flask
	app = Flask(__name__)

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

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

# uWSGI起動

いちいち手動で立ち上げなくていいよう、起動スクリプトに登録する。
また、複数立ち上げられるよう、`Emperor`とかいう仕組みを利用する。

```sh
mkdir -p /var/{run,log}/uwsgi
chown -R nginx:nginx /var/{run,log}/uwsgi
mkdir -p /etc/uwsgi/vassals
ln -sf /var/www/アプリディレクトリ/uwsgi.ini /etc/uwsgi/vassals/アプリディレクトリ.ini
```
※/etc/uwsgi/vassals配下に各アプリのiniファイルへのシンボリックリンクを張る
※nginx:nginxの部分は起動ユーザーに応じて書き換える

```sh
vim /etc/uwsgi/emperor.ini
```

```ini
[uwsgi]
emperor = /etc/uwsgi/vassals
uid = nginx
gid = nginx
logto = /var/log/uwsgi/uwsgi.log
touch-logreopen = /var/log/uwsgi/touch-logreopen
master = true
vacuum = true
ignore-sigpipe = true
ignore-write-errors = true
disable-write-exception = true
```

## [CentOS 7の場合] /etc/systemd/system/uwsgi.service の作成

```ini
[Unit]
Description=uWSGI Emperor
After=syslog.target

[Service]
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /var/log/uwsgi
ExecStartPre=-/bin/mkdir -p /var/run/uwsgi
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/emperor.ini
ExecStartPost=-/bin/chown -R nginx:nginx /var/log/uwsgi
ExecStartPost=-/bin/chown -R nginx:nginx /var/run/uwsgi
ExecStopPost=rm -rf /var/run/uwsgi
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target
```
※環境によっては、 `/usr/bin/mkdir` の場合あり。
※環境によっては、 `/usr/local/bin/uwsgi` の場合あり。
※環境によっては、 nginxユーザーではない場合あり。

```sh
systemctl enable uwsgi.service
systemctl start  uwsgi.service
```

## [CentOS 6の場合] /etc/init.d/uwsgi の作成

https://zafiel.wingall.com/archives/7513 から拝借し、起動コマンドは以下の様に書き換えた。

```
daemon $PROG --master --emperor /etc/uwsgi/vassals --die-on-term --uid nginx --gid nginx -d $UWSGI_LOG --pidfile $PID
```

```sh
chmod 755 /etc/init.d/uwsgi
service uwsgi start
chkconfig uwsgi on
```

# nginxと連携

TLS証明書を事前に作っておく。

```nginx
upstream backend {
	server    127.0.0.1:8080;
	keepalive 128;
}

server {
	listen       80;
	server_name  ドメイン名;

	location / {
		rewrite ^.*$ https://ドメイン名$request_uri last;
	}
}

server {
	listen       443;
	server_name  ドメイン名;

	#charset koi8-r;
	#access_log  /var/log/nginx/log/host.access.log  main;

	ssl                  on;
	ssl_certificate      /etc/pki/tls/certs/ドメイン名.crt;
	ssl_certificate_key  /etc/pki/tls/private/ドメイン名.nopass.key;
	ssl_protocols        TLSv1;
	ssl_ciphers          HIGH:!ADH:!MD5:!DES:!3DES;

	location / {
		set $do_not_cache 1;

		proxy_pass http://backend;
		proxy_no_cache     $do_not_cache;
		proxy_cache_bypass $do_not_cache;
		proxy_cache zone1;
		proxy_cache_key    $scheme://$proxy_host$uri$is_args$args;
		proxy_cache_valid  200 10m;
	}

	#error_page  404       /404.html;

	# redirect server error pages to the static page /50x.html
	#
	error_page   500 502 503 504  /50x.html;
	location = /50x.html {
		root   /usr/share/nginx/html;
	}
}

server {
	listen       8080;
	server_name  ドメイン名;
	root /var/www/アプリディレクトリ/public;

	access_log  /var/log/nginx/access_8080.log  main;

	location / {
		try_files $uri @rewrite;
	}
	location @rewrite {
		include uwsgi_params;
		uwsgi_pass unix:///var/run/uwsgi/アプリディレクトリ.sock;
		uwsgi_connect_timeout 600s;
		uwsgi_read_timeout 600s;

		uwsgi_param SERVER_ENV development;
	}
}
```

```sh
service nginx restart
```

# 動作確認

```
https://ドメイン名/
```

`Hello World!` と表示された。