Ubuntu 14.04 LTSでvenvを利用して速攻でPython3.4 + Nginx + uWSGI + FlaskなWebアプリケーション実行環境を作る


Ubuntu 12.04でpyenvを利用して速攻でPython3.4 + Nginx + uWSGI + FlaskなWebアプリケーション実行環境を作る
http://qiita.com/5t111111/items/e170fead91261621b054

この14.04版ではpyenv依存をやめてvenvだけを使うようにしています。

## 登場人物

- ぼく  
  去年まで女子校だった私立高校に通う普通の高校生。人間が嫌い。これ以降登場しない。
- Ubuntu  
  Linuxらしいが、よく知らない。
- venv  
  Pythonの実行環境を切り替えるやつ。標準でついてくるようになったらしいが、よく知らない。
- Nginx  
  Webサーバーらしいが、よく知らない。
- uWSGI  
  WSGIサーバーらしいが、何のことか分からない。そもそもWSGIを知らない。
- Flask  
  Webアプリケーションを気軽に作れる軽量のフレームワークらしいが、よく知らない。

## Nginxのインストール

### Nginxのstableリポジトリを追加

```none
$ sudo add-apt-repository ppa:nginx/stable
```

### いつものupdate/upgrade

```none
$ sudo apt-get update
$ sudo apt-get upgrade
```

### Nginxのインストールと起動

```none
$ sudo apt-get install nginx
$ sudo /etc/init.d/nginx start
```

ブラウザで接続し、Nginxのgreetingsページが表示されることを確認する。

![スクリーンショット 2014-04-19 23.55.07.png](https://qiita-image-store.s3.amazonaws.com/0/29846/d88f7c8b-2bfc-5447-8313-890a655385ce.png "スクリーンショット 2014-04-19 23.55.07.png")


## flaskサンプルアプリケーションの構築

### アプリケーションのディレクトリを作成

アプリケーションのディレクトリを作成。
アプリケーションの関連ファイルは、venv仮想環境を含めすべてこの中に格納する。

```none
$ sudo mkdir -p /var/www/demoapp
```

ユーザー権限がrootのままだとあれなので、自分の利用しているユーザーに変更しておく

```none
$ sudo chown -R username:username /var/www/demoapp/
```

### サンプルアプリケーション用のvenvの作成

<font color="#ff0000">残念ながら現在、Python 3.4でvenvの作成はうまくいかないみたいです。
http://qiita.com/5t111111/items/1643ba04104e75589ad4</font>

なので、`--without-pip`オプションを付けてvenvを作ってから、手動でpipをインストールする必要があります。

```none
$ pyvenv-3.4 --without-pip /var/www/demoapp/venv
$ source /var/www/demoapp/venv/bin/activate
$ mkdir ~/src
$ cd ~/src
$ curl -O https://pypi.python.org/packages/source/s/setuptools/setuptools-3.4.4.tar.gz
$ tar xvfz setuptools-3.4.4.tar.gz
$ cd setuptools-3.4.4/
$ python setup.py install
$ cd ..
$ curl -O https://pypi.python.org/packages/source/p/pip/pip-1.5.4.tar.gz
$ tar xvfz pip-1.5.4.tar.gz
$ cd pip-1.5.4/
$ python setup.py install
```

## Flaskのインストール

### venvの有効化

```none
$ source /var/www/demoapp/venv/bin/activate
```

### Flaskのインストール

```none
$ pip install flask
```

### Flaskアプリケーションの作成

`/var/www/demoapp/hello.py`を作成。

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

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

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

### flaskアプリケーションの起動テスト

venvを有効にした状態で。

```none
$ python /var/www/demoapp/hello.py
```

webブラウザでサーバーのポート:8080に接続し確認。
![スクリーンショット 2014-04-19 23.55.19.png](https://qiita-image-store.s3.amazonaws.com/0/29846/8d95938c-5455-32c9-f756-4168ee4c9bc4.png "スクリーンショット 2014-04-19 23.55.19.png")

## Nginxの設定

### デフォルトのサイト設定(の、シンボリックリンク)を削除

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

### サンプルアプリケーション用の設定ファイルを作成

`/var/www/demoapp/demoapp_nginx.conf` を作成

```
server {
    listen      80;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;

    location / { try_files $uri @yourapplication; }
    location @yourapplication {
        include uwsgi_params;
        uwsgi_pass unix:/var/www/demoapp/demoapp_uwsgi.sock;
    }
}
```

_uWSGIサーバーはUNIXソケット or TCPでWebサーバーであるNginxと通信する。
上記の設定ではUNIXソケットでの通信を指定している。
`uwsgi_pass unix:/var/www/demoapp/demoapp_uwsgi.sock;`_

Nginxの設定ファイルのディレクトリにシンボリックリンクを貼る

```none
$ sudo ln -s /var/www/demoapp/demoapp_nginx.conf /etc/nginx/sites-enabled/
```

### Nginxの再起動

```none
$ sudo /etc/init.d/nginx restart
```

webブラウザでサーバーに接続し確認。
**この時点では、uWSGIサーバーが起動していないため、このように"502 Bad Gateway"のエラーが出るはず。**
![スクリーンショット 2014-04-20 0.26.56.png](https://qiita-image-store.s3.amazonaws.com/0/29846/c01c9cf4-f6e4-fbc1-0751-56e049625284.png "スクリーンショット 2014-04-20 0.26.56.png")

## uWSGIのインストール

### uWSGI用のvenv環境の構築

uWSGIはaptからもインストール可能だが、少々バージョンが古いのでpipで最新のものをインストールする。

uWSGIは今後複数アプリケーションで共用すると思うので、アプリケーション用のvenv内にインストールするのではなく別で用意するが、システムのPython環境は弄りたくないので、ここでは`/opt`以下にやはりvenvでuWSGI用の環境を作成する。

アプリケーション用の `demoapp` venvを有効化していたらdeactivateしておく。

```none
$ deactivate
```

### uWSGIのビルドに必要なパッケージのインストール

以下が必要になるのでインストールする。

- Cコンパイラ
- Python3ヘッダ

```none
$ sudo apt-get install build-essential python3-dev
```

### uWSGI用のvenv作成

`/opt`以下に作るのでrootで作業を行うが、気になる場合には別の場所や権限を変更しても構わない。
その場合は以下の設定でuWSGIバイナリのパスなどを修正する必要がある。

アプリケーション用のvenvを作ったときと同様に、通常の方法ではうまくいかないので、手動でpipのインストールを行う。(めんどい・・・)
以下は、アプリケーション用のvenvを作ったときのソースは残っているものとして手順を記載。

```none
$ sudo -s
# pyvenv-3.4 --without-pip /opt/venv/uwsgi
# source /opt/venv/uwsgi/bin/activate
# cd ~/src
# cd setuptools-3.4.4/
# python setup.py install
# cd ..
# cd pip-1.5.4/
# python setup.py install
```

### uWSGIのインストール

```none
$ source /opt/venv/uwsgi/bin/activate
$ pip install uwsgi
```

## uWSGIの設定

### アプリケーションのuWSGI設定ファイルを作成する

`/var/www/demoapp/demoapp_uwsgi.ini` を作成

```none
[uwsgi]
#application's base folder
base = /var/www/demoapp

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

#virtualenv folder
virtualenv = /var/www/demoapp/venv

pythonpath = %(base)

#socket file's location
socket = /var/www/demoapp/%n.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
```

### ログ出力先ディレクトリの作成

```none
$ sudo mkdir -p /var/log/uwsgi
$ sudo chown -R username:username /var/log/uwsgi
```

## uWSGIの起動

```none
$ uwsgi --ini /var/www/demoapp/demoapp_uwsgi.ini
```

webブラウザでサーバーに接続し確認。
NginxとuWSGIが問題なくソケット通信できていれば、`Hello World!`が表示される。
![スクリーンショット 2014-04-20 11.05.01.png](https://qiita-image-store.s3.amazonaws.com/0/29846/d07c6c55-7719-2c7c-3e6f-8cff8839d26f.png "スクリーンショット 2014-04-20 11.05.01.png")


# uWSGI Emperor

uWSGI EmperorはuWSGIの設定ファイルを読み込んでuWSGIプロセスを起動する機能。
複数の設定を読み込みプロセス起動を一括管理することができる。

## Upstartファイルの作成

`/etc/init/uwsgi.conf` を作成

```none
description "uWSGI"
start on runlevel [2345]
stop on runlevel [06]
respawn

env UWSGI=/opt/venv/uwsgi/bin/uwsgi
env LOGTO=/var/log/uwsgi/emperor.log

exec $UWSGI --master --emperor /etc/uwsgi/vassals --die-on-term --uid www-data --gid www-data --logto $LOGTO
```

上記の最後の行は、`/etc/uwsgi/vassals`に存在する設定ファイルを探しuWSGIデーモンを起動することを意味しているので、
サンプルアプリケーションのuWSGI設置ファイルへのシンボリックリンクを`/etc/uwsgi/vassals`に作成。

```none
$ sudo mkdir -p /etc/uwsgi/vassals
$ sudo ln -s /var/www/demoapp/demoapp_uwsgi.ini /etc/uwsgi/vassals
```

## 権限の設定

uWSGIデーモンを`www-data`ユーザーで起動する設定としている。
したがって、アプリケーションとログのディレクトリのオーナーを`www-data`にしておく。

```none
$ sudo chown -R www-data:www-data /var/www/demoapp/
$ sudo chown -R www-data:www-data /var/log/uwsgi/
```

NginxとuWSGIが同一の`www-data`ユーザーで動作するため、ソケットのパーミッションを644に変更しておく。

`/var/www/demoapp/demoapp_uwsgi.ini` を編集

```
...
#permissions for the socket file
chmod-socket = 644
```

## uWSGIの起動

```none
$ sudo start uwsgi
```

webブラウザでサーバーに接続し確認。
ここまですべて問題なければ、`Hello World!`が表示される。

# 終わりに

一応これでFlaskアプリケーションを動かせるところまではできました。
注意点というか突っ込みどころは色々あるかと思います。
特にNginxとuWSGIの周りは、それぞれのドキュメントやググって設定を詰めてください。

## 参考
http://vladikk.com/2013/09/12/serving-flask-with-nginx-on-ubuntu/