Python Flaskアプリを nginx + uWSGI 環境下へデプロイしたのでメモ

こんばんは、ころすけ(@wg_koro)です。

さよならGoogle Reader

先日、Google Reader終了カウントダウンページを作りました。この時に使ったのがPython+Flask。

ローカルで作って、さあサーバーへデプロイしよう・・・という時にふと気づいた。

「今更mod_pythonはないなぁ。せっかくだからuWSGIにしよう!」

というわけで、今回、カウントダウンページはFlask + nginx + uWSGIで構築しました。この構築時のメモをつらっと書き記します。

uWSGI

超簡単。

$ pip install uwsgi

以上w!

インストールはさくっとできたので、動かしてみる。ドキュメントを参考に、簡単なFlaskアプリを書いて試す。

[python]
#!/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ファイルとして使えるので、ダイレクトに指定する。

[plain]
$ uwsgi –http :9090 –wsgi-file /var/www/example.py
[/plain]

これで動く。確認するにはブラウザで9090ポートへアクセスするか、サーバー内から http://localhost:9090/ へwgetする。正常に動作していれば、HTMlが返ってくる。

次に、作ったFlaskアプリケーションを動かしてみる。Flaskはvirtualenv環境下で作ったので、uwsgi起動時にvirtualenv下のディレクトリパスを指定しないとダメ。
参考:uWSGI+virtualenv+Flask | おいぬま日報

[plain]
$ 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)にしてしまう。

[plain]
[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!

[plain]
$ uwsgi uwsgi.ini
[/plain]

次に、uwsgiがサーバー再起動時に自動で走るように、サービス起動スクリプトを作る。

[shell]
#!/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の設定ファイルは結構シンプル。

[shell]
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アプリ書く時はこれで決まりかな〜。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください