nginxでDjangoを使うときの設定ファイル:クライアント、nginx、uwsgiの流れを整理しよう
nginx (nginx/1.13.9) で Django を使うときの設定を整理する。Linux は CentOS 7 とする。結論は下のコードになる。
server {
listen 80;
server_name ***.***.***.***;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location / {
uwsgi_pass 127.0.0.1:8001;
include ***/uwsgi_params;
}
}
nginx の設定ファイル
nginx の設定ファイルは二つ(以上)ある。
- /etc/nginx/nginx.conf
- /etc/nginx/conf.d/default.conf
Django などのプロジェクトを管理するための設定は二番目の /etc/nginx/conf.d/default.conf に記す。一番目の設定ファイルに設定を上書きしている解説をよく見かけるが、推奨されない。
nginx が設定ファイルを分けている理由を知るために、一番目のファイル /etc/nginx/nginx.conf を vi で確認しよう。デフォルトは次のようになっている。
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
サーバーというよりは nginx そのものの設定に近い。最後の行に
include /etc/nginx/conf.d/*.conf;
とある。これは /etc/nginx/conf.d/ ディレクトリにある拡張子が conf のファイルを読みこむという意味である。最初の説明のとおり nginx の設定ファイルは二種類あった。
- /etc/nginx/nginx.conf
- /etc/nginx/conf.d/default.conf
/etc/nginx/nginx.conf が親、/etc/nginx/conf.d/default.conf が子という関係にあることがわかってきたと思う。
親 /etc/nginx/nginx.conf
子 /etc/nginx/conf.d/default.conf
Django の設定は子ファイルに書くようにする。
説明(nginx)
最初にあげたコードを見てみよう。コードのうち本質は次の部分である。
listen 80;
server_name ***.***.***.***;
location / {
uwsgi_pass 127.0.0.1:8001;
include ***/uwsgi_params;
}
コードの意味を理解するためには nginx と uwsgi の働きについて知らなければいけない。クライアント(サイトを見る人)が Django で作ったサイトを見るとき、次のように進む。
クライアント
↓
nginx
↓
uwsgi
↓
Django
nginx と uwsgi の解説を読むときはサーバーという単語に気をつけないといけない。特に Apache と PHP を触ってきた人にとって、自分が考えているサーバーと Django が想定しているサーバーのイメージは違うだろう。
クライアントは最初に nginx に入る。クライアントはサーバーのマシンがある IP アドレスを知っているが、nginx は(自分がそのマシンにあるにもかかわらず)知らない。またクライアントはポート番号をあらかじめ指定している。HTTP のポートは 80、HTTPS は 443 である。
クライアントの要求は IP アドレスとポート番号である(他にもたくさんあるが、今はこの二つだけを考えることにしよう)。この二つを nginx が確認することで、nginx はクライアントにページの情報を渡すことが可能になる。そのために
listen 80;
server_name ***.***.***.***;
と書く。※が続いている部分はあなたの nginx がある IP アドレスである。通常は四桁である。こうした部分にくわしくない方は、ぜひ nginx をさくらサーバーなどのリモートマシンにインストールしてみよう。ローカル環境に nginx を入れているだけでは、ここを実践的に理解することは難しい。
この時点でクライアントは nginx に接続した。しかし nginx が返す情報(レスポンス)は記述されていない。この情報は URL と紐づいている。例えば /aaa.html という URL には A というレスポンス、/bbb.html という URL には B というレスポンスにしたいときは
location /aaa.html {
A
}
location /bbb.html {
B
}
とする。しかし私たちが考えているサイトは動的であり、すべてのページを一つずつこのように記述したら効率が悪い。そもそもこうした作業をしないように Django が開発されたのである。
Django はすべてのページを一つのプログラムで表示するプログラムである。そこで nginx の設定には
location / {
Django
}
と書いて、どのような URL が要求されても nginx は Django というものを返すようにする。こうして /aaa.html の情報を要求されても Django と応え、/bbb.html のページを表示するようにいわれても Django と応えるようになった。
ここまでを読んで nginx が何をしているかだんだんわかってきたと思う。もし内容の半分を理解できなかったら、nginx ではなく Apache の解説を読むことをおすすめする。
続いて私たちにとって不幸なことは、nginx が Django を直接使うことができないということだ。
説明(uwsgi)
location / {
Django
}
と記述することで nginx はすべてのアドレスに対してとりあえず Django を返すようになった。Django は Python のプログラムであり、nginx とは直接やりとりできない。両者の間に入るものが uwsgi である。
uwsgi とは何かという問いはここではかなり不毛である。あえてサーバーという言葉を使うとすると、uwsgi は内部のサーバーということになる。
nginx は直接 Django に会うことができないため、まずは uwsgi にコンタクトをとる。コンピューター内部でしか使わないアドレス 127.0.0.1:8001 が uwsgi の住所である。くりかえすが、この住所はコンピューター内部のもので、外部のクライアントからは見えないものだ。
location / {
uwsgi_pass 127.0.0.1:8001;
}
このように記述して nginx は uwsgi に会うことができた。というよりは処理を uwsgi を丸投げしたのである。あとは uwsgi から情報が届くのを待つだけである。uwsgi からやってきた情報をクライアントに流すことが nginx の主な役割といってもいいだろう。
最後に。nginx は uwsgi にコンタクトをとるとき、クライアント(外部から接続してきた人)の情報をガバッと渡す。ただ「こんにちは」というだけだったら、uwsgi も何をすればいいかわからない。このときに渡される情報が uwsgi_params である(と今は考えることにしよう)。
以上から次の設定が完成する。
listen 80;
server_name ***.***.***.***;
location / {
uwsgi_pass 127.0.0.1:8001;
include ***/uwsgi_params;
}
uwsgi_params
ようやく最後にして最も難解な部分 uwsgi_params の話になった。以上の手順をふまえて Django がきちんと表示されないとすれば、半分以上の確率で uwsgi_params の内容またはパスに異常がある。
そもそも uwsgi_params はどこにあるのだろうか?結論からいうとあなたが作っている Django のプロジェクトの直下である。もしプロジェクトが aaa というプログラム名だったら aaa というディレクトリの直下に uwsgi_params がある。
この話のどこに悲劇的な誤解があるかというと(多くの解説サイトを見て多くの人が混乱に陥るのは)、Django プロジェクトで aaa というプログラムを作ると、その直下に aaa というディレクトリが作られるからである。結局 aaa プログラムのディレクトリ構造は次のようになる。
aaa
- aaa
- manage.py
- uwsgi_params
この構造はぜひ頭に入れてほしい。ごちゃごちゃいっても、結局これだけなのだ。必ず uwsgi_params を manage.py と同じ階層に入れよう。
uwsgi_params がプロジェクトディレクトリ直下に入っていることに安心したら、続いて uwsgi_params の絶対パスを調べよう。例えば CentOS の一般ユーザーにプロジェクトが入っているときは、次のようになるかもしれない。
/home/banana/www/aaa/uwsgi_params
banana は一般ユーザー、aaa は Django のプロジェクト名である。この絶対パスを include に指定する。
listen 80;
server_name ***.***.***.***;
location / {
uwsgi_pass 127.0.0.1:8001;
include /home/banana/www/aaa/uwsgi_params;
}
これで設定ファイルが本当の意味で完成した。
続いて uwsgi_params の中身である。これはお決まり文句で今はあれこれ考える必要がない。ほぼすべての解説サイトで用意されているデフォルトは次のとおりである。
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
しつこいようだが、この内容がある uwsgi_params というファイルは Django プロジェクトの直下にあることに注意しよう。ちなみにこのファイルは特殊であり、拡張子はいらない。このファイルはプロジェクトを作った時点で必要になるため、Django で新しくプロジェクトを作ったら最初に作るようにしよう。
終わり
これで nginx の設定は終わった。これで問題があるとすれば nginx ではなく uwsgi にあると考えるべきだ。uwsgi は nginx から uwsgi_params というものを受けとり、いろいろ処理して、結果を nginx に伝える。
注意深く観察しなければいけないところは uwsgi が本当に uwsgi_params を受けとっているかどうかという点である。つまり nginx は渡したつもりでも、実は uwsgi は渡されていないのかもしれない。
あるいは nginx は「uwsgi は 127.0.0.1:8001 というアドレスにある」と考えているのに、uwsgi はそのアドレスにないのかもしれない。