暇人じゃない

nginx + FastCGI で Django を動かす
DjangoLinuxNginxPythonServerUbuntu

nginx + FastCGI で Django を動かすメモです。

環境: Ubuntu 10.04 nginx 0.8.53 MySQL 5.1.41 Python 2.6.5 Django 1.2.3

下準備

pip のインストール pip でパッケージ管理を行うようにします。 easyinstall をインストールして、easyinstall で pip をインストールします。

% sudo aptitude install python-setuptools
% sudo easy_install pip

これ以降は virtualenv で作成したサンドボックスにパッケージをインストールしています。 virtualenv って何?という方は以下の記事を読んでみると幸せになれます。

参考:Python 開発環境 | Go for it! http://blog.mitsukuni.org/2010/10/25/python-development-environment 参考:virtualenv, virtualenvwrapper, pip を使う方法 - Ian Lewis http://www.ianlewis.org/jp/virtualenv-pip-fabric

Django のインストール Django!! Django!!

% sudo pip install django

flup のインストール FastCGI を使用するためのライブラリです。

% sudo pip install flup

mysql-python のインストール Python から MySQL に接続するためのライブラリです。

# mysql_config が入っていなかったのでインストール
% sudo aptitude install libmysqlclient-dev
# Python のヘッダファイル/静的ライブラリをインストール
# (インストールしないと mysql-python のインストールでコケる)
% sudo aptitude install python-dev
% pip install mysql-python

FastCGI の設定

Django FastCGI の起動スクリプトを作成 以下のサイトから引っ張ってきて、編集します。

参考:InitdScriptForLinux - Django - Trac http://code.djangoproject.com/wiki/InitdScriptForLinux

今回の環境だと以下のようになります。

/etc/init.d/django-fastcgi

#! /bin/bash
### BEGIN INIT INFO
# Provides:          FastCGI servers for Django
# Required-Start:    networking
# Required-Stop:     networking
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: Start FastCGI servers with Django.
# Description:       Django, in order to operate with FastCGI, must be started
#                    in a very specific way with manage.py. This must be done
#                    for each DJango web server that has to run.
### END INIT INFO
#
# Author:  Guillermo Fernandez Castellanos
#          <guillermo.fernandez.castellanos AT gmail.com>.
#
# Version: @(#)fastcgi 0.1 11-Jan-2007 guillermo.fernandez.castellanos AT gmail.com
#

#### SERVER SPECIFIC CONFIGURATION
DJANGO_SITES="hogeproject"
SITES_PATH=/var/www/hoge/public_html
RUNFILES_PATH=/tmp/run
VIRTUALENV_PATH=/home/chocoby/.virtualenvs
HOST=127.0.0.1
PORT_START=3000
RUN_AS=www-data
FCGI_METHOD=prefork
#### DO NOT CHANGE ANYTHING AFTER THIS LINE!

set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="FastCGI servers"
NAME=$0
SCRIPTNAME=/etc/init.d/$NAME

#
#       Function that starts the daemon/service.
#
d_start()
{
    # Starting all Django FastCGI processes
    PORT=$PORT_START
    for SITE in $DJANGO_SITES
    do
        echo -n ", $SITE"
        if [ -f $RUNFILES_PATH/$SITE.pid ]; then
            echo -n " already running"
        else
            source $VIRTUALENV_PATH/$SITE/bin/activate
            start-stop-daemon --start --quiet \
                       --pidfile $RUNFILES_PATH/$SITE.pid \
                       --chuid $RUN_AS --exec /usr/bin/env -- python \
                       $SITES_PATH/$SITE/manage.py runfcgi \
                       method=$FCGI_METHOD \
                       host=$HOST port=$PORT pidfile=$RUNFILES_PATH/$SITE.pid
            chmod 400 $RUNFILES_PATH/$SITE.pid
        fi
        let "PORT = $PORT + 1"
    done
}

#
#       Function that stops the daemon/service.
#
d_stop() {
    # Killing all Django FastCGI processes running
    for SITE in $DJANGO_SITES
    do
        echo -n ", $SITE"
        start-stop-daemon --stop --quiet --pidfile $RUNFILES_PATH/$SITE.pid \
                          || echo -n " not running"
        if [ -f $RUNFILES_PATH/$SITE.pid ]; then
           rm $RUNFILES_PATH/$SITE.pid
        fi
    done
}

ACTION="$1"
case "$ACTION" in
    start)
        echo -n "Starting $DESC: $NAME"
        d_start
        echo "."
        ;;

    stop)
        echo -n "Stopping $DESC: $NAME"
        d_stop
        echo "."
        ;;

    restart|force-reload)
        echo -n "Restarting $DESC: $NAME"
        d_stop
        sleep 1
        d_start
        echo "."
        ;;

    *)
        echo "Usage: $NAME {start|stop|restart|force-reload}" >&2
        exit 3
        ;;
esac
exit 0

元々のスクリプトから何点か変更しています。それも含めて設定する部分を説明します。 元々の項目

  • /bin/bash : source コマンドを使用するので /bin/sh から /bin/bash に変更
  • DJANGO_SITES :Django のプロジェクト名を指定
  • SITES_PATH :プロジェクトディレクトリが存在しているディレクトリのパスを指定
  • RUNFILES_PATH :プロセス ID を記録しておく .pid ファイルを設置するディレクトリのパスを指定
  • FCGI_METHOD :threaded から prefork に変更

新たに追加した項目

  • VIRTUALENV_PATH : virtualenv のサンドボックスが置いてあるディレクトリのパス

今回は virtualenv を使用しているので、FastCGI を起動する前にプロジェクト用の virtualenv を activate しています。 VIRTUALENV_PATH にサンドボックスが置かれているディレクトリのパスを指定します。

サンドボックス名は DJANGO_SITES で設定しているプロジェクト名と対応させます。 51 行目に追加しているのですが、start-stop-daemon コマンドの前に source コマンドを使用し、そのサンドボックス内の /bin/activate を実行することによって、サンドボックスを activate しています。 こうすることで、プロジェクト毎にサンドボックス内のパッケージを使用できるようになります。(@key3++)

virtualenv を使用しない場合は追加する必要はありません。

scp などで転送した場合は所有者を変更しておく

% sudo chown root:root /etc/init.d/django-fastcgi

システム起動時に起動させる

% sudo update-rc.d django-fastcgi defaults

.pid ファイルを置いておくディレクトリを作成する 作成する場所は、起動スクリプトの RUNFILES_PATH に書いてあるディレクトリ。

% sudo mkdir /tmp/run
% sudo chown www-data:www-data /tmp/run

nginx の設定

サイトを置いておくディレクトリを作成

% sudo mkdir -p /var/www/hoge/{logs,public_html}

public_html の中にプロジェクトのディレクトリを置く 例:/var/www/hoge/public_html/hogeproject

nginx の設定ファイルを作成 /etc/nginx/sites-available/hoge

server {
    listen  80;
    server_name hoge;
    access_log  /var/www/hoge/logs/access.log;
    error_log   /var/www/hoge/logs/error.log;

    location / {
        fastcgi_pass 127.0.0.1:3000;
        include /etc/nginx/fastcgi_params_django;
    }

    location /static {
        root /var/www/hoge/public_html/hogeproject;
    }

    location /media {
        alias /home/chocoby/.virtualenvs/hogeproject/lib/python2.6/site-packages/django/contrib/admin/media;
    }
}

/static は、プロジェクトの CSS ファイルや画像素材などの静的ファイルが置いてあるのディレクトリ。 /media は、管理画面の静的ファイルが置いてあるディレクトリ。

元々ある、/etc/nginx ディレクトリの fastcgiparams を include していると、**SCRIPTNAME** が渡されてトップページのみしか表示されない現象が発生してしまうので 削除しておきます。(@key3++) それに加えて Django 用のパラメーターも追加。

sites-available の設定に直接パラメーターを書いても良いのですが、再利用することを考えて、/etc/nginx ディレクトリに fastcgiparamsdjango というファイルを作成し include するようにしています。

/etc/nginx/fastcgiparamsdjango

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# Django
fastcgi_param  PATH_INFO          $fastcgi_script_name;
fastcgi_pass_header               Authorization;
fastcgi_intercept_errors          off;

sites-enabled ディレクトリにシンボリックリンクを張って有効化

% sudo ln -s /etc/nginx/sites-available/hoge /etc/nginx/sites-enabled

FastCGI を起動し、nginx に設定を再読込させる

% sudo /etc/init.d/django-fastcgi start
% sudo nginx -s reload

あとは、settings.py を環境に合わせ、manage.py syncdb などをして完了です。

About

chocoby (GitHub / Twitter)

フリーのソフトウェア開発者です。 Ruby を使った Web 開発を得意としています。