こんばんは、ころすけ(@wg_koro)です。
先日、Google Reader終了カウントダウンページを作りました。この時に使ったのがPython+Flask。
ローカルで作って、さあサーバーへデプロイしよう・・・という時にふと気づいた。
「今更mod_pythonはないなぁ。せっかくだからuWSGIにしよう!」
というわけで、今回、カウントダウンページはFlask + nginx + uWSGIで構築しました。この構築時のメモをつらっと書き記します。
uWSGI
超簡単。
$ pip install uwsgi
以上w!
インストールはさくっとできたので、動かしてみる。ドキュメントを参考に、簡単なFlaskアプリを書いて試す。
#!/usr/bin/env python
# examle.py
from flask import Flask
app = Flask(__name__)
@app.route(‘/’)
def index():
return "<span style=’color:red’>I am app 1</span>"
[/python]
Flaskは起動ファイルがそのままWSGIファイルとして使えるので、ダイレクトに指定する。
$ uwsgi –http :9090 –wsgi-file /var/www/example.py
[/plain]
これで動く。確認するにはブラウザで9090ポートへアクセスするか、サーバー内から http://localhost:9090/ へwgetする。正常に動作していれば、HTMlが返ってくる。
次に、作ったFlaskアプリケーションを動かしてみる。Flaskはvirtualenv環境下で作ったので、uwsgi起動時にvirtualenv下のディレクトリパスを指定しないとダメ。
参考:uWSGI+virtualenv+Flask | おいぬま日報
$ uwsgi -s /tmp/mysock.sock –http :9090 -H /home/myaccount/.virtualenvs/bye –python-path /var/www/myapp -w app:app –processes 3 –threads 2
[/plain]
これでOK。
ミソは下記の通り。
- -H: virtualenv下のディレクトリパスを指定
- –python-path: Flaskアプリを設置しているディレクトリ
- -w: Flaskオブジェクトを代入した変数名・・・であってるのかな? app = Flask(__name__) ←コレ
毎回、このオプションを指定するのはしんどいので、設定ファイル(uwsgi.ini)にしてしまう。
[uwsgi]
socket = /tmp/mysock.sock
http = :9090
venv = /home/smaster/.virtualenvs/bye
python-path = /var/www/deploy/current/source
wsgi = app:app
processes = 3
threads = 2
[/plain]
起動時はこの設定ファイルを呼び出すだけでOK!
$ uwsgi uwsgi.ini
[/plain]
次に、uwsgiがサーバー再起動時に自動で走るように、サービス起動スクリプトを作る。
#!/bin/bash
#
# bye-reader start script
#
# chkconfig: 345 99 1
# description: uwsgi start script
# processname: uwsgi
# pidfile: /tmp/uwsgi.pid
#
# Source function library.
. /etc/init.d/functions
PROGNAME="uwsgi"
PID="/tmp/$PROGNAME.pid"
LOCK="/tmp/$PROGNAME.lock"
RETVAL=0
UWSGI_HOME="/home/myaccount/.virtualenvs/venvdir"
UWSGI_BIN="$UWSGI_HOME/bin/uwsgi"
UWSGI_APP_DIR="/var/www/"
UWSGI_APP_BIN="$UWSGI_APP_DIR/deploy/current/source"
UWSGI_LOG="/var/log/uwsgi/$PROGNAME.log"
UWSGI_APP_INIT="$UWSGI_APP_DIR/uwsgi.ini"
PROG=$UWSGI_BIN
[ -f $PROG ] || exit 0
start() {
echo -n "Starting $PROGNAME: "
daemon $PROG $UWSGI_APP_INIT –uid nginx –gid nginx -d $UWSGI_LOG –master –pidfile $PID
echo
[ $RETVAL = 0 ] && touch $LOCK
return $RETVAL
}
stop() {
echo -n "Stopping $PROGNAME: "
killproc -p $PID $PROGNAME -INT
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f $LOCK $PID
}
show_status() {
status $PROGNAME
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
show_status
;;
*)
echo "Usage: $PROGNAME {start|stop|restart|status}"
RETVAL=2
;;
esac
exit $RETVAL
[/shell]
/etc/init.d/uwsgi として設置し、パーミッションを変更。
こうすると service uwsgi start/stop/restart で動かすことが可能。
ついでに
sudo chkconfig –add uwsgi
sudo chkconfig uwsgi on
として、自動起動するようにする。
nginx
nginxの設定ファイルは結構シンプル。
server {
listen 80;
server_name goodbyereader.wingall.com;
access_log /var/log/nginx/bye.access_log.log main;
error_log /var/log/nginx/bye.error_log.log;
location ~ /static/.*\.(jpg|JPG|gif|GIF|png|PNG|swf|SWF|css|CSS|js|JS|inc|INC|ico|ICO) {
root /var/www/deploy/current/source/;
index index.html;
log_not_found on;
expires 30d;
break;
}
location / {
proxy_cache czone;
proxy_cache_valid 200 1m;
proxy_cache_valid 404 5m;
include uwsgi_params;
uwsgi_pass unix:/tmp/mysock.sock;
}
}
[/shell]
静的ファイルだけnginxで受けて、残りはuwsgiへ流す。これでできあがり!
意外と楽に組み込むことができました。迷った箇所はあまり無い感じ。uwsgiは結構シンプルなので、PythonでWebアプリ書く時はこれで決まりかな〜。