nginx + uwsgi + django on dockerでサイトを構築し,localhost上で公開するまでの解説です.
webサーバーの動き方に関して
djangoにはpython3 manage.py runserver
で起動できる便利な開発サーバー機能が備わっています.
しかし,本番環境ではこの機能は使わずに,apacheやnginxなどのwebサーバーを使用することが推奨されています.
今回は,nginxを使用してdjangoアプリケーションデプロイすることにします.
また,環境の移植性を考慮して,dockerを使用したデプロイを行います.
nginx + uwsgi + djangoの具体的な処理の流れはこちらで解説されていますので,ぜひ参照してください.
非常に分かりやすく書かれており,これを読むだけである程度の設定はできてしまいます.
Setting up Django and your web server with uWSGI and nginx
簡単に図解すると,下の図のようにリクエストが流れていくことになります.
webクライアント -> nginx(80,443ポート) -> uwsgi(8000ポート) -> djangoバックエンド
- nginxがwebサーバーとして機能しwebクライアントからリクエストを受け取る.
- uwsgiがアプリケーションサーバーとしてnginxからのリクエストを受け取る.
- uwsgiがdjangoを動かし,結果のレスポンスを返す
この構成を実現するため,以下ではnginx, uwsgi, djangoの各項目の設定事項を見ていきます.
docker-compose.yml
の中身
まず,全体の見通しをよくするために,docker-compose.yml
の中身を紹介しておきます.
version: "3"
services:
nginx:
image: nginx:latest
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./django-project/myapp/static:/static
- ./django-project/myapp/media:/media
ports:
- 8000:80
environment:
- LANG=C.UTF-8
- LANGUAGE=en_US
depends_on:
- django-project
- mysql
django-project:
build: ./django-project
restart: always
command: bash /init.sh
tty: true
volumes:
- ./django-project/app:/myapp
- ./django-project/init.sh:/init.sh
environment:
- DEBUG=False
- LOCALHOST=localhost
- DEPLOYHOST=#デプロイ先のドメイン名
depends_on:
- mysql
- redis-server
mysql:
# mysqlに関する記述
....
各ファイルのフォルダ構成
project/
|__django-project/
| |__myapp/
| | |__myapp/
| | |__static/
| | |__media/
| | |__manage.py
| |__Dockerfile
|__nginx
| |__conf/nginx.conf
| |__uwsgi_params
|__mysql
|__docker-compose.yml
nginxの設定内容
まずnginxの設定を行います.
ホストOS側で./nginx/conf/nginx.conf
を作成し,に以下の項目を書き足していきます.
upstream django {
ip_hash;
server django-project:8000;
}
server {
listen 80;
charset utf-8;
client_max_body_size 75M;
location /static {
alias /static;
}
location /media {
alias /media;
}
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
上記のポイントは,以下です.
- upstreamでuwsgiサーバーを示すホスト名:ポート名を指定
listen 80
で80番ポートをリッスン
location /static, location /media
で静的ファイルの場所を指定.docker-compose.yml
内でマウントした/static, /media
内のファイルを探します.
location /
でuwsgiをリクエストを流す先として指定します.uwsgi_params
はここからコピペで問題ありません.
uwsgiの設定内容
uwsgiはdjangoと同じdockerイメージの中に入れます../django-project/Dockerfile
内に以下の内容を書き加えます.
FROM python:3.8-slim-buster
# djangoなど必要なライブラリをインストール
COPY ./requirements.txt /requirements.txt
# RUN source /venv/bin/activate
RUN python3.8 -m pip install --upgrade pip
RUN python3.8 -m pip install -r requirements.txt
RUN python3.8 -m pip install uwsgi # uwsgiを入れること
これでdjangoをuwsgiで動かす準備はできました.
次にuwsgiでリクエストを待ち受けるために,コンテナ起動時に実行するシェルスクリプトを書いていきます.
#!/bin/bash
cd /myapp;
bash -c "python3 manage.py makemigrations";
bash -c "python3 manage.py migrate";
bash -c "python3 manage.py collectstatic --noinput"
bash -c "uwsgi --socket :8000 --module myapp.wsgi --py-autoreload 1s";
uwsgi(8000番ポート)で待ち受けることを最後の行で書き加えています.
djangoの設定内容
最後に,djangoの設定を行なっていきます.
変更が必要なのは,/myapp/myapp/settings.py
のみです.
- デバッグモードのON/OFFをdocker-compose.ymlから指定できるようにする.
docker-compose.yml
のenvironment
でDEBUG=True/False
と指定することでデバッグモードが変えられるように,環境変数の読み込み部分を追記します.
また,djangoはDEBUG=False
の際には外部からの通信を受け付けないので,ALLOWED_HOSTS
にも環境変数の読み込みを追加します.
DEPLOYHOST
の部分にデプロイするサーバーのホスト名を書きます.
# settings.py
# SECURITY WARNING: don't run with debug turned on in production!
is_debug_mode = os.environ.get("DEBUG")
DEBUG = (is_debug_mode == "True")
ALLOWED_HOSTS = [os.environ.get("LOCALHOST"), os.environ.get("DEPLOYHOST")]
- nginxが静的ファイルをサーブできるように,staticファイルのルートを指定する.
STATIC_ROOT
とMEDIA_ROOT
を指定することで,DEBUG=False
の際に静的ファイルはnginxが直接サーブするようにできます.
# settings.py
STATIC_URL = '/static/'
STATICFILE_DIRS = [
os.path.join(BASE_DIR, 'userctrl/static/'),
os.path.join(BASE_DIR, 'contest_manage/static/'),
os.path.join(BASE_DIR, 'ace-builds')
]
STATIC_ROOT = os.path.join(BASE_DIR, "static")
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"