という機会があったので、その時の荒削りメモ。
バックエンドサーバはuWSGI
Nginx + Gunicorn という構成がどうやらメジャーらしいですが、何もわからん状態で調査していた際に先に出会ったuWSGIを採用することにしました。
ということで、実は後はほぼuWSGIのセットアップのお話。
uWSGI 1.0 まではAPTで一発だったわけだが。。
uWSGIの 2012年08月 現在の最新版はversion1.2なのですが、以下 ubuntu12.04(x86_64) で実行した結果。
$ > aptitude show uwsgi Package: uwsgi New: yes State: not installed Version: 1.0.3+dfsg-1ubuntu0.1 Priority: optional Section: universe/web Maintainer: Ubuntu DevelopersArchitecture: amd64 Uncompressed Size: 128 k Depends: uwsgi-core (= 1.0.3+dfsg-1ubuntu0.1), lsb-base, initscripts (>= 2.88dsf-13.3) Recommends: sqlite3 Conflicts: uwsgi Description: fast, self-healing application container server uWSGI presents a complete stack for networked/clustered web applications, implementing message/object passing, caching, RPC and process management. It uses the uwsgi protocol for all the networking/interprocess communications. uWSGI can be run in preforking, threaded, asynchronous/evented modes and supports various forms of green threads/coroutines (such as uGreen, Greenlet, Fiber). uWSGI provides several methods of configuration: via command line, via environment variables, via XML, INI, YAML configuration files, via LDAP and more. On top of all this, it is designed to be fully modular. This means that different plugins can be used in order to add compatibility with tons of different technology on top of the same core. This package depends on uWSGI core binary and installs: * init.d script for running uWSGI daemon(s) with options defined in custom user-created configuration files * infrastructure for running daemons (like common locations of communication sockets, logs) Homepage: http://projects.unbit.it/uwsgi/
ってな感じでltsな1.0.x 止まりなわけで、
しかもPPA漁ってみてもそれらしいものもないわけで、
最新のuWSGIを使う場合はちゃんとコンパイルなりpip使うなりで入れる必要があります。
pip使えばインストールは結構簡単
てなわけでpipでuWSGIをインストールします。- まずは必要なパッケージのインストール
■ laughk@ubuntu12.04 ================================= sudo aptitude install \ python-pip \ build-essential \ python-dev
■ laughk@ubuntu12.04 ================================= sudo pip install uwsgi以上!
ここまではホントにラク。
ただ、この段階だと純粋に uwsgi コマンドが入っただけなので、
サーバにプロセスと常駐させる場合なんかはダルいです。
ということで起動スクリプト書くよ!
uWSGIのtar玉の中とか見てもテンプレートっぽいのが無いんですな。なので、ここはUbuntu側で用意されているテンプレート、/etc/init.d/skelton を元に作成。
差分は以下の様な感じ。
--- /etc/init.d/skeleton 2012-04-14 18:26:31.000000000 +0900 +++ /etc/init.d/uwsgi 2012-07-12 15:15:53.402515557 +0900 @@ -1,16 +1,15 @@ #! /bin/sh ### BEGIN INIT INFO -# Provides: skeleton +# Provides: uwsgi # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: Example initscript -# Description: This file should be used to construct scripts to be -# placed in /etc/init.d. +# Short-Description: Starts the uwsgi server +# Description: Starts uwsgi using start-stop-daemon ### END INIT INFO # Author: Foo Bar <foobar@baz.org> # # Please remove the "Author" lines above and replace them # with your own name if you copy and modify this script. @@ -18,13 +17,15 @@ # Do NOT "set -e" # PATH should only include /usr/* if it runs after the mountnfs.sh script -PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="Description of the service" -NAME=daemonexecutablename -DAEMON=/usr/sbin/$NAME -DAEMON_ARGS="--options args" +PATH=/usr/local/sbin:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin +DESC="uWSGI Server Process" +NAME="uwsgi-web" +DAEMON="/usr/local/bin/uwsgi" +UWSGI_CONF_DIR="/usr/local/uwsgi/conf" +UWSGI_CONF_INI="django-app.ini" +DAEMON_ARGS=" --enable-thread --ini ${UWSGI_CONF_DIR}/${UWSGI_CONF_INI}" PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 @@ -51,7 +52,7 @@ # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 - start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + start-stop-daemon --start --background --quiet --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready @@ -69,17 +70,16 @@ # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME - RETVAL="$?" - [ "$RETVAL" = 2 ] && return 2 + # start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. - start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON - [ "$?" = 2 ] && return 2 + start-stop-daemon --stop --quiet --oknodo --retry=0/5/KILL/5 --pidfile $PIDFILE --exec $DAEMON + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" @@ -100,19 +100,19 @@ case "$1" in start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + 0|1) log_end_msg 0 ;; + 2) log_end_msg 1 ;; esac ;; stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + 0|1) log_end_msg 0 ;; + 2) log_end_msg 1 ;; esac ;; status)オプション(DAEMON_ARGS)とかはまあ状況にあわせてね。。
ちなみに
上記のように起動スクリプトを作成する場合のオペレーションは以下のような感じ。
■ laughk@ubuntu12.04 ================================ ## プロセスは www-data ユーザーで実行させたいのでパーミッション調整 sudo chown www-data `which uwsgi` sudo chmod +xs `which uwsgi` ## テンプレートからコピー sudo cp /etc/init.d/skelton /etc/init.d/uwsgi ## 上記の差分になるように編集 sudo vim /etc/init.d/uwsgi ## 確認 diff -u /etc/init.d/skelton /etc/init.d/uwsgi ## デフォルト起動の設定 sudo update-rc.d uwsgi default
設定ファイルとか設置
基本的に先ほどの差分のものにあわせてやると以下の様な感じ。- django-app.iniの例 (詳細はぐぐってくださいませ)
[uwsgi] chdir = /path/to/django-app pythonpath = /path/to/django-app env = DJANGO_SETTINGS_MODULE=django-app.settings module = django.core.handlers.wsgi:WSGIHandler() socket = 127.0.0.1:8000 logto = /var/log/uwsgi/django-app.log
■ laughk@ubuntu12.04 ================================ ## 設定ファイル置き場の作成 & 移動 sudo mkdir -p /usr/local/uwsgi/conf cd /usr/local/uwsgi/conf ## djangoアプリの環境にあわせて設定を作成 vim django-app.ini ## ログ置き場の作成 sudo mkdir -p /var/log/uwsgi sudo touch /var/log/uwsgi/django-app.log ## パーミッション調整 sudo chown -R www-data {/var/log,/usr/local}/uwsgiこれでuWSGIの最低限のセットアップはOKなはず。
Nginx側の設定
NginxはPPAもあるし、aptでさくっとね。設定ファイルは以下の様な感じで。
- /etc/nginx/sites-available/hogehoge.com の例
server { server_name hogehoge.com; access_log /var/log/nginx/hogehoge.com-access.log; error_log /var/log/nginx/hogehoge.com-access.log warn; location / { allow all; include uwsgi_params; uwsgi_pass 127.0.0.1:8000; } localtion /static { allow all; alias /path/to/django-app/static; } }
■ laughk@ubuntu12.04 ================================== ## Nginxのインストール sudo aptitude install nginx ## もろもろ設定。 cd /etc/nginx/sites-enabled sudo rm default sudo vim ../sites-available/hogehoge.com sudo ln -s ../sites-available/hogehoge.com ## 設定反映 sudo service nginx configtest sudo service nginx reload
というような感じ。
あとはuWSGIを起動
これで /path/to/django-app にデプロイしたいDjangoアプリをおいてsyndbかけるなりしてuWSGIを起動。■ laughk@ubuntu12.04 ============================== sudo service uwsgi start
とりあえずサーバで動かす際はこんなものでOKなはず。