Nginx+uWSGI+Flask+Ubuntuで作る本格サーバー(実装編)

[インストール編](https://qiita.com/8128/items/471061e40c5a243a4cd6)からの続き

各アプリケーションのざっくりとした説明とインストールは
[前回の記事](https://qiita.com/8128/items/471061e40c5a243a4cd6)を参照

<h1>Flask</h1>
以下の構造になるようなファイルを作っていく

```
flask_web_application/
├── application/
│   ├── __init__.py
│   └── views.py
└── server.py
```

まずappというFlaskの本体を作成

```python:__init__.py
from flask import Flask

app = Flask(__name__)

import application.views
```

ルートディレクトリにアクセスしたら
"Hello, World"とだけ返す

```python:views.py
from application import app

@app.route('/')
def show_entries():
    return "Hello World"
```

uWSGIが実行するファイル
ようするにここから処理がスタート

```python:server.py
from application import app

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

ちなみに今回は<code>/home/ubuntu/application/</code>に作ったが
他のディレクトリの場合は
uWSGIを実行するユーザーにchownで権限を渡し
chmodで権限を「775」あたりにしておくこと
後々説明するが今回はuWSGIを

グループ名:www-data
ユーザー名:www-data

で実行している

<h1>uWSGI</h1>
まずuwsgi.iniを作成
uwsgi.iniはuwsgiを起動するときに読み込む設定ファイル

起動時に読み込むだけのものなのでどこに置いてもいいが
わかりやすく今回作っているFlaskアプリケーション
の直下にでも置いとく

```uwsgi.ini

[uwsgi]
base = /home/ubuntu/application/flask_web_application

module = server:app

virtualenv = /home/ubuntu/py36_flask_server

pythonpath = %(base)

callable = app

uid = www-data
gid = www-data
master = true
processes = 1
threads = 1
socket = /tmp/uwsgi.sock
chmod-socket = 666
vacuum = true
die-on-term = true
thunder-lock = true
```

主要な部分だけ

|変数|説明|
|:---|:---|
|base|アプリケーションのディレクトリ|
|module|app = Flask(\_\_name\_\_)で作ったappのこと|
|virtualenv|Pythonの仮想環境のディレクトリ|
|pythonpath|baseと同じ|
|callable|呼び出すモジュール(app)|
|uid|ユーザー名で実行|
|gid|グループ名で実行|
|processes|環境とアプリケーションによるがコア数がおすすめ|
|threads|<b>Flask</b>が使うスレッドの数、Flaskをマルチスレッドで実行すること自体おすすめしない(GIL問題)|
|socket|UNIXドメインソケット|

uid、gidで指定するユーザー名・グループ名はあらかじめ作っておく
www-dataなら既に存在しているはず
指定しないとrootで実行することになるのでセキュリティ上あまりよろしくない

そのた諸々、参考になる記事
https://uwsgi-docs.readthedocs.io/en/latest/ThingsToKnow.html
https://qiita.com/yasunori/items/64606e63b36b396cf695
https://qiita.com/wapa5pow/items/f4326aed6c0b63617ebd
https://qiita.com/11ohina017/items/da2ae5b039257752e558

<h2>uWSGIをサービスに追加</h2>

```
$ sudo vi /etc/systemd/system/uwsgi.service

#下記を追加
[Unit]
Description=uWSGI
After=syslog.target

[Service]
ExecStart=/home/ubuntu/py36_flask_server/bin/uwsgi --ini /home/ubuntu/application/flask_web_application/uwsgi.ini
# Requires systemd version 211 or newer
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target
```

ExecStartに仮想環境にインストールしたuWSGIを
--iniに先ほど作った設定ファイルを指定します

サービスにuWSGIを追加

```
$ sudo systemctl enable uwsgi
```

<h1>Nginx</h1>
デフォルトのNginxウェルカムページを消す

conf.d/default.confがあるなら削除

```
$ sudo rm /etc/nginx/conf.d/default.conf
```

/nginx/sites-enabled/defaultがあるなら削除

```
$ sudo rm /etc/nginx/sites-enabled/default
```

これでデフォルトサイトは消える

sites-availableとsites-enabledがない場合作成しておく

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

<h3>sites-available と sites-enabledは結局なんなのか</h3>
基本的には一つのサーバーで複数のドメインを使うためのもので
管理がしやすくなる

ただ今回は別に複数のドメインを使うわけではないのだが
Ubuntu+Nginx+uWSGIという構造上
conf.dを使うより安定する

使い方は
・sites-availableにドメイン別の設定ファイルを作成
・sites-enabledにsites-availableのシンボリックリンクを張る

という至って簡単なもの
シンボリックリンクはいわゆるショートカット

/etc/nginx/nginx.confのhttpブロック部分の
/etc/nginx/conf.d/*.confを書き換える

```
$ sudo vi /etc/nginx/nginx.conf

http{
…
include /etc/nginx/conf.d/*.conf;
}
```

↓

```
http{
…
include /etc/nginx/sites-enabled/*;
}
```

/etc/nginx/sites-available/myapplication.confを追加

```
$ sudo vi /etc/nginx/sites-available/myapplication.conf

# 下記を追加
server {
    listen       80;
    root /var/www/html;
    location / { try_files $uri @yourapplication; }
    location @yourapplication {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
}
```

ざっくり説明するとtry_filesでURLそのままを
rootから検索、なかったらuWSGIに(URLそのままで)内部リダイレクトするという構造
rootは特になにも入っていない
全部uWSGIに丸投げしてもいいのだけど公式は上記みたいになっている

uwsgi_paramsはuWSGIの設定ファイル
unix:///tmp/uwsgi.sockはUNIXドメインソケット
といわれるものでようするにこれでuWSGIとの通信を行う

他にTCPで接続したりもできるがポートを占領してしまうので
ドメインソケットを使った方がよい

ショートカットを作ればnginxの設定は終わり

```
$ sudo ln -s /etc/nginx/sites-available/myapplication.conf /etc/nginx/sites-enabled/myapplication
```

<h1>アクセス</h1>
ここらへんで一旦システムごと再起動することを推薦
できない場合はNginxだけは再起動する

```
$ sudo systemctl restart nginx
```

uwsgiを起動していないなら起動

```
& sudo systemctl start uwsgi
```

uwsgiのエラーチェック

```
$ sudo systemctl status uwsgi
```

nginxのエラーチェック

```
$ sudo systemctl status nginx
```

一通り読んでエラーがなさそうならアクセスしてみる

```
$ curl http://127.0.0.1
Hello, World
```

<h1>まとめ</h1>
基本的に静的ファイルはNginxに処理させた方が早い

間違っているこうした方がよいという箇所があったら教えてください