はじめに
Djangoを使ったアプリをデプロイする時にuWSGIとNginxが必要らしいと聞いて、役割や関係を理解するのに時間がかかったので書いておきます
ここでは、DjangoとuWSGI、Nginxの役割や関係について解説していきます。
まずは登場人物を紹介
-
ブラウザ
Chromeとかedgeとかですね
-
Django (ジャンゴ)
Pythonのフレームワークの一つです。
Pythonのフレームワークは、WSGI(Web Server Gateway Interface)という仕様で作られています。
WSGIは、webサーバとpython製のWebアプリケーションをつなぐために必要な規格です。
他には Flask や Bottle があります。
-
uWSGI(ウィズギー)
アプリケーションサーバです。
WSGIの仕様を満たすWebアプリを動かすためのアプリケーションサーバをWSGIサーバーと言います。 WSGIサーバーの一つがuWSGIです。
他にGunicornやNGINX Unitがあります。
「ウィズギー」と発音しますが、言いにくいので自分は「上杉さん」と呼んでいます。
-
Nginx (エンジンエックス)
Webサーバソフトの一つです。
Webサーバとは、ブラウザから「このページのファイルを頂戴」と言われたら「ほれどうぞ」と渡すやつです。
ブラウザがそのファイルを表示することで人間はwebページを見ることができます。
「Webサーバのソフト」は WebサーバをWebサーバたらしめている中身のことです。パソコンにNginxを入れたらWebサーバとして動きます。他に Apache や IIS があります。
-
データベース
ブラウザであれこれ入力したものを保存しておく場所です
上杉さん(uWSGI)たちの関係は?
ではお三方が何をする人でどんな関係なのかを見ていきます。
例として、通販の商品詳細ページを開いたとしましょう
- ブラウザが「商品詳細ページを表示して」とリクエストする
- Nginxが、リクエストをuWSGIに送る
- uWSGIが、Djangoに「商品情報とHTMLを頂戴」と命令する
- Djangoが、データベースに「この商品情報を検索して」と命令する
- データベースが、Djangoに「ほれ、商品情報だよ」と渡す
- Djangoが、uWSGIに「ほれ、商品情報とHTMLだよ」と渡す
- uWSGIが、Nginxに「商品情報とHTMLだよ」と渡す
- Nginxが、商品画像やらHTML、CSS、javaScriptなどの静的ファイルを準備する
- Nginxが、商品の詳細情報と静的ファイルを一緒にしてブラウザに送る
ブラウザからリクエストをもらうと、
NginxはuWSGIを通じてDajngoに伝え、
DjangoがuWSGIを通じて必要な情報を送り、
Nginxは画像などの静的ファイルと一緒にブラウザに返します
まるでバケツリレーみたいですね。図にするとこんな感じです。
【備忘録】Nginx、uWSGI、Djangoの接続
ここからは、備忘録としてNginx、uWSGI、Djangoの接続方法を残します。
--- NginxとuWSGIをつなぐ ---
必要なファイルは3つです。
- uwsgi.ini (uWSGI設定ファイル)
- uwsgi.params ( WSGI 変数 を定義)
- nginx.conf (Nginxの設定ファイル)
接続方法として、ポートを指定して接続する場合とソケット通信する方法がありますが、今回はポートを指定して接続する場合で書きます。
chdir = /code
module = myproject.wsgi:application
master = true
processes = 4
vacuum = true
die-on-term = true
env = PYTHONPATH=/code
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;
upstream django {
server 127.0.0.1:8000; # TCP ポートで通信
}
server {
listen 80;
server_name localhost;
charset utf-8;
location /static/ {
alias /code/static/; # 静的ファイルの場所
}
location / {
uwsgi_pass django; # Nginx が uWSGI に接続する
include uwsgi_params;
}
}
server_tokens off;
--- DjangoをuWSGIで動かす ---
uwsgi --ini /path/to/uwsgi.ini
もし、Dockerコンテナを起動するのであれば、
compose.ymlファイルの、Djangoコンテナの設定の中で下記のように変更します。
# uWSGIとNginxを使わない場合
# command: python3 manage.py runserver 0.0.0.0:8000
# uWSGIとNginxを使う場合
command: bash -c "apt-get update && \
apt-get install -y libpcre3 libpcre3-dev && \
uwsgi --ini /code/uwsgi.ini"
これでコンテナ起動時にDjangoコンテナでuWSGIの起動コマンドを実行します
まとめ
DjangoとuWSGI、Nginxの役割と関係について自分なりの理解をまとめてみました。
「結局、上杉さんってリクエストを右から左に流してDjangoに命令してるだけで何もしてないじゃん」って思った方、それは違います。
食事中「ソース取って」と言われたシーンを思い出してください。めっちゃ長いテーブルの端同士だったら、1人の手渡しでは届きませんよね。
上杉さんも同じです。多分。
参考文献