revision-up-to: | 17812 (1.4) |
---|
Django を動作させるプラットフォームとして現在推奨しているのは WSGI ですが、多くの 人々が使っている共有ホスティングサービスには、 FastCGI や SCGI, AJP といっ たプロトコルしか選択肢がありません。
Note
このドキュメントでは、 FastCGI に重点をおいて説明しています。 SCGI や
AJP といったプロトコルも、Python パッケージ flup
経由でサポートして
います。 SCGI や AJP 固有の設定は、後述の 「 プロトコル 」の節を参照し
てください。
FastCGI は、いわば外部アプリケーションによって Web サーバにページを提供させ る方法の一つです。Web サーバは (socket を介して) 受け取った Web リクエスト の処理を FastCGI に肩代りさせます。 FastCGI はコードを実行して、その応答を Web サーバに返します。 Web サーバはその内容をクライアントのWeb ブラウザに返 すというわけです。
WSGI と同様、 FastCGI はコードをメモリ上に残すので、リクエストはスクリプトの起 動時間を伴わずに処理されます。 ただし、例えば mod_wsgi が Apache Web サーバプロセスの 中に組み込まれるか、別のデーモンプロセスとして実行されるかを設定できるのに対 し、 FastCGI プロセスは Web サーバプロセスの中ではなく、別の永続的プロセスの中 で実行されます。
なぜ別のプロセスでコードを実行するのですか?
Apache における伝統的な mod_*
の構成では、 Web サーバのプロセス空間
内に様々なスクリプト言語 (有名なのは PHP, Python, Perl です) を埋め込ん
で実行します。この構成は、リクエストのたびにプログラムコードをディスク
から読み出さなくてもよくなるため、起動時間を減らせるという利点がありま
す — その反面、メモリの消費は莫大になります。
FastCGI の性質上、Web サーバプロセスと別のユーザアカウントでプロセスを 実行できます。この特徴は、自分のコードを他のユーザから守れるという点で、 共有ホストにおいてセキュリティ上の利点になります。
Django で FastCGI を使うには、まず flup をインストールせねばなりません。 flup は FastCGI を使えるようにするための Python ライブラリです。 Django は バージョン0.5 以降の flup で動作します。
FastCGI はクライアントサーバモデルで動作します。ほとんどの場合、 FastCGI プ ロセスを自分で起動することになるでしょう。 Web サーバ (Apache、 lighttpd な ど) が Djagno の FastCGI プロセスにアクセスするのは、サーバが動的ページをロー ドするときだけです。デーモンは常にコードをメモリ上にロードしたまま動作して いるので、非常に高速に応答を返せるのです。
Note
共有ホスティングサービスを使っているなら、Web サーバで管理された FastCGI プロセスを使わざるを得ないかもしれません。 Django を Web サーバ で管理された FastCGI プロセスで使うには、後に出て来る節の説明を参照して ください。
Web サーバが FastCGI サーバにアクセスするには二つの方法があります。一つは Unix ドメインソケット (Win32 システムにおける「名前付きパイプ」) で、もう一 つは TCP ソケットです。どちらを選ぶかは好みの問題です。パーミッションの問題 から、通常は TCP ソケットの方が簡単です。
サーバを起動するには、プロジェクトのあるディレクトリ (manage.py
のある
場所) に移動して、 manage.py の
runfcgi
コマンドを実行します:
./manage.py runfcgi [options]
runfcgi
に help
オプションだけを指定すると、利用可能な全ての
オプションを表示します。
引数として、 socket
, protocol
, または、
host
および port
を指定せねばなりません。さらに、
Web サーバをセットアップする際に、FastCGI サーバを起動するときに使ったソケット
名か、ホスト/ポート番号の組合せを指定せねばなりません。後述の 実行例 を参照
してください。
Django は flup のサポートしている全てのプロトコル、すなわち fastcgi,
SCGI, AJP1.3 (Apache JServ プロトコルバージョン 1.3) をサポートしていま
す。使いたいプロトコルを指定するには、 protocol=
を
./manage.py runfcgi
のオプションに指定します。 <protocol_name>
は
fcgi
(デフォルト)、 scgi
または ajp
のいずれかです。例を以下に
示します:
./manage.py runfcgi protocol=scgi
TCP ポートを使い、スレッドモードでサーバを起動する場合:
./manage.py runfcgi method=threaded host=127.0.0.1 port=3033
Unix ドメインソケットを使い、 prefork モードでサーバを起動する場合:
./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid
ソケットのセキュリティ
Django のデフォルトの umask では Web サーバと Django の fastcgi が同じグ
ループ かつ 同じユーザで実行されることが必要です。セキュリティを強固に
するには同じグループの別のユーザで実行させることができます。こうする場合は
runfcgi
の umask
引数を使って umask に 0002 をセットします。
デーモン化 (バックグラウンド化) させずにプロセスを起動する場合 (デバッグ時 に便利です):
./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1
フォアグラウンドでプロセスを走らせているのなら、止めるのは簡単で、
Ctrl-C
を押して FastCGI サーバを止めるだけですみます。バックグラウンド
プロセスを使っているのなら、 Unix の kill
コマンドを使わねばなりません。
pidfile
オプションを指定して runfcgi
を起動しているの
なら、以下のようにして起動中の FastCGI デーモンを殺せます:
kill `cat $PIDFILE`
$PIDFILE
は起動時に指定した pidfile
の値です。
Unix 上で FastCGI デーモンを簡単に再起動させたいなら、以下のようなシェルス クリプトを試してみましょう:
#!/bin/bash
# 以下の 3 つの設定は自分の環境に合わせて置き換える
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"
cd $PROJDIR
if [ -f $PIDFILE ]; then
kill `cat -- $PIDFILE`
rm -f -- $PIDFILE
fi
exec /usr/bin/env - \
PYTHONPATH="../python:.." \
./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE
Django を Apache と FastCGI の構成で使うには、 Apache をインストールし、さ らに mod_fastcgi をインストールして有効にせねばなりません。詳しい手順は Apache のドキュメントを参照してください。
mod_fastcgi の構成が終ったら、 httpd.conf
ファイルを編集して、 Apache
に Django の FastCGI インスタンスを教えます。以下の二つの設定を行わねばなり
ません:
FastCGIExternalServer
ディレクティブを使って、 FastCGI サーバの場
所を指定します。mod_rewrite
を使って、リクエストが適切な FastCGI に向くようにしま
す。FastCGIExternalServer
ディレクティブは、 Apache に FastCGI サーバの探し
方を教えます。 FastCGIExternalServer のドキュメント にもある通り、
socket
または host
のいずれかを指定せねばなりません。それぞれの例を
以下に示します:
# ソケットや名前付きパイプを経由して FastCGI に接続する場合
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock
# TCP でホスト名とポート番号を指定して接続する場合
FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033
いずれのケースでも、 /home/user/public_html/mysite.fcgi
は実際に存在し
なくてもかまいません。このパスは Web サーバが内部的に使う URL に過ぎず、
FastCGI で処理すべきリクエストを URL で区別するための単なるフックです。(次
節で詳しく説明します)
第二ステップでは、特定のパターンに一致する URL では FastCGI を使うよう
Apache に指示します。前節で述べたように、 mod_rewrite モジュールを使って、
URL を mysite.fcgi
(または FastCGIExternalServer
ディレクティブに指
定した名前) に書き換えます。
下記の例では、ファイルシステム上に存在せず、かつパスが /media/
で始まら
ないファイルに対するリクエストに対して FastCGI を使うよう Apache に指示して
います。Django の admin サイトを使っているなら、これはよくある状況でしょう:
<VirtualHost 12.34.56.78>
ServerName example.com
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]
</VirtualHost>
Django は、 {% url %}
テンプレートタグ (や、同様のメソッド) で
URL を構築する際、自動的にリライト前の URL を使います。
FastCGI 経由でアプリケーションを提供する別の方法が、 Apache の mod_fcgid モ
ジュールを使うことです。 mod_fastcgi と比べると、 mod_fcgid の FastCGI アプリ
ケーションの扱い方は、ワーカープロセスを自分自身で生成し、
FastCGIExternalServer
のような何かを提供するのではないところが異なります。
このため設定が少し違った外見になります。
実際には、後ほど 共有ホスティング環境 での Django の動作について説明するのと同じように、スクリプトハンドラを追加すること になります。もっと詳しく知るには、どうぞ mod_fcgid リファレンス を参照して ください。
lighttpd は静的ファイルのサービスによく使われている軽量な Web サーバです。 lighttpd はネイティブの FastCGI サポートを持っているので、 Apache の縛りが なくて、動的ページと静的ページの両方をサービスしたい場合には良い選択肢とい えます。
mod_fastcgi
がモジュールリストに入っているか確かめてください。このとき、
mod_rewrite
や mod_access
よりも後ろにして、 mod_accesslog
より
も前にします。 admin メディアファイルを提供するなら、 mod_alias
も必要
になるでしょう。
lighttpd 設定ファイルに以下の設定を追加してください:
server.document-root = "/home/user/public_html"
fastcgi.server = (
"/mysite.fcgi" => (
"main" => (
# TCP で fastcgi に接続する場合は host / port を指定する
# "host" => "127.0.0.1",
# "port" => 3033,
"socket" => "/home/user/mysite.sock",
"check-local" => "disable",
)
),
)
alias.url = (
"/media/" => "/home/user/django/contrib/admin/media/",
)
url.rewrite-once = (
"^(/media.*)$" => "$1",
"^/favicon\.ico$" => "/media/favicon.ico",
"^(/.*)$" => "/mysite.fcgi$1",
)
lighttpd には、ホストごとに設定をカスタマイズするための「条件付き設定 (conditional configuration)」があります。複数の FastCGI サイトを指定するに は、各サイトごとに FastCGI 設定を条件分岐のブロックにします:
# If the hostname is 'www.example1.com'...
$HTTP["host"] == "www.example1.com" {
server.document-root = "/foo/site1"
fastcgi.server = (
...
)
...
}
# If the hostname is 'www.example2.com'...
$HTTP["host"] == "www.example2.com" {
server.document-root = "/foo/site2"
fastcgi.server = (
...
)
...
}
fastcgi.server
ディレクティブに複数のエントリを追加すれば、複数の
Django を同じサイトでも駆動できます。各エントリごとに FastCGI ホストを追加
してください。
Cherokee はとても高速で柔軟性があり、簡単に設定できる Web サーバです。 Cherokee は、FastCGI, SCGI, PHP, CGI, SSI, TLS や SSL による暗号化、バーチャ ルホスト、認証、動的エンコーディング、ロードバランシング、Apache 互換のログ ファイル、データベースのバランサ、リバース HTTP プロキシなどなど、最近の Webサーバがサポートしている様々な技術をサポートしています。
Cherokee プロジェクトのページには、 Cherokee で Django を運用する ための ドキュメントがあります。
共有ホスティングプロバイダの多くでは、独自のサーバデーモンを起動できなかっ
たり、 httpd.conf
ファイルを編集できなかったりします。このような場合で
も、サーバ起動プロセスを使えば Django を駆動できます。
Note
この章で説明するような方法で Web サーバ起動プロセスを使う場合、 FastCGI サーバを自分で起動する必要はありません。Apache が必要に応じて複数のプロ セスを起動してくれます。
Web コンテンツのルートディレクトリ下に、以下のような内容のファイルを
.htaccess
という名前で保存します:
AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
次に、 Apache に FastCGI プログラムの起動方法を教える小さなスクリプトを作成
します。 mysite.fcgi
というファイルを作成して Web コンテンツディレクト
リに置き、実行可能にします:
#!/usr/bin/python
import sys, os
# Python のモジュール検索パスをカスタマイズする
sys.path.insert(0, "/home/user/python")
# カレントディレクトリをプロジェクトのディレクトリに移す (必要なら)
# os.chdir("/home/user/myproject")
# 環境変数 DJANGO_SETTINGS_MODULE を設定する
os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")
これはサーバが mod_fastcgi を使っている場合に動作します。一方、 mod_fcgid を
使っている場合、 .htaccess
ファイルでの少しの変更を除けば、セットアップは
ほとんど同じです。 fastcgi-script ハンドラを追加する代わりに、 fcgi-handler を
追加する必要があります:
AddHandler fcgid-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]
サイトを構成する Python コードを変更した場合、 FastCGI にコードが変更された
ことを教えねばなりません。しかし、 FastCGI の場合には Apache を再起動する必
要はありません。その代わり、 mysite.fcgi
を再度アップロードするか、ファ
イルを編集して、タイムスタンプを更新してください。 Apache は、ファイルのタ
イムスタンプが更新されていることを発見すると、Django アプリケーションを再起
動してくれます。
Unix システムでコマンドラインシェルへのアクセスが許されているなら、
touch
コマンドを使えば簡単にタイムスタンプを更新できます:
touch mysite.fcgi
サーバやその設定がどうあれ、何らかの形で admin メディアファイルを提供する方 法を考えておかねばなりません。 modwsgi のドキュメントには、上記の構成でも使えるアドバイスがあります。
FastCGI を使った設置方法は、ほとんどが URL をリライトしてウェブサーバ内部の
別の場所を指すようにしています。このとき、 Django から見えるパス情報には、
もともとの URL が反映されません。そのため、 Django アプリケーションを特定の
プレフィクスの下で動かしていて、 {% url %}
タグで表示される
URL を、 mysite.fcgi
のようなリライト後のものでなく、プレフィクスのついた
URL にしたいときに問題が生じます。
Django は実際のスクリプト名プレフィクスが何だったかをそれなりにうまく調べよ
うとします。特に、ウェブサーバが SCRIPT_URL
を設定する場合(Apache の
modo_rewrite 特有の機能です) や、 REDIRECT_URL
を設定する場合 (Apache
と mod_rewrite をある構成で使ったとき) には、もとのプレフィクスを自動的に
見つけ出します。
Django がプレフィクスを正しく見付けられない場合や、リライト前の値を URL に
使いたい場合には、設定ファイル中で FORCE_SCRIPT_NAME
を設定して
ください。この変数には、全ての URL に共通なスクリプト名を指定します。したがっ
て、別々のスクリプト名を持った URL に対応するには個別に設定ファイルを用意せ
ねばなりませんが、そのようなケースは稀でしょう。
例えば、全てのコンテンツを '/'
以下の URL で提供するように Django を構
成しているなら、設定ファイルには FORCE_SCRIPT_NAME = ''
と指定してくだ
さい。
Oct 26, 2017