Djangoのrunserverコマンドで動かすサーバーは、あくまで簡易的な開発用サーバーです。本番運用する場合にはセキュリティやパフォーマンスの観点からWebサーバー(リバースプロキシ)とApplicationサーバー(WSGIサーバー)を別途構築する必要があります。
今回、WebサーバーにはNginxを、アプリケーションサーバーにはGunicornを用いてDocker上に構築します。
環境
ソフト | バージョン |
---|---|
OS | MacOS Catalina 10.15.7 |
docker engine | 20.10.5 |
docker compose | 1.29.0 |
Django | 3.2.5 |
Gruncorn | 20.1.0 |
Nginx | 1.17.7 |
ディレクトリ構成
.
├── app # Djangoアプリ
├── config # Django設定関係
│ ├── local_settings.py
│ ├── settings.py
│
├── Dockerfile
├── docker-compose.yml
├── docker.env
├── gunicorn.conf
├── manage.py
└── requirements.txt
Django設定ファイル
開発環境用にlocal_settings.pyファイルを作成し、'SECRET_KEY'、'DEBUG'、'ALLOWED_HOSTS'のデフォルト設定はそちらに移行。
開発用サーバーを起動する際には、settingsオプションで'local_settings.py'ファイルを指定する。
from .settings import *
SECRET_KEY = 'XXXXX'
DEBUG = True
ALLOWED_HOSTS = []
# 開発用サーバ起動コマンド
# python manage.py runserver --settings config.local_settings
settings.pyファイルには本番環境設定を記述する。'SECRET_KEY'、'ALLOWED_HOSTS'は環境変数からの引用とし、'DEBUG'はFalseにする。
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
DEBUG = False
ALLOWED_HOSTS = list(os.environ.get('ALLOWED_HOSTS','localhost').split(' '))
STATIC_URL = '/static/'
STATICFILES_DIRS = [str(BASE_DIR / 'static')]
STATIC_ROOT = str(BASE_DIR / 'static_root')
Dockerファイルの設定
Dockerコンテナ内にpython環境を構築し、requirements.txtで定義したDjangoとGunicornをインストール。
gunicornコマンドでGunicornを起動し、config/wisg.pyを読み込み、UNIXドメインソケットをバインドする。
FROM python:3.9.6-alpine
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
RUN mkdir -p /var/run/gunicorn
CMD ["gunicorn", "config.wsgi", "--bind=unix:/var/run/gunicorn/gunicorn.sock"]
Django==3.2.5
gunicorn==20.1.0
Docker Composeファイルの設定
gunicornイメージはDockerファイルからbuildし、nginxイメージはDocker Hubからダウンロードする。
gunicornコンテナ、nginxコンテナの双方でgunicronボリュームにマウントし、UNIXソケット通信を行う。
コンテナ内のnginx設定ファイル(default.conf)をホスト側で作成したgunicorn.confファイルにマウントする。
Djangoアプリの'DJANGO_SECRET_KEY'と'ALLOWED_HOSTS'は環境変数として設定する。
version: '3'
services:
gunicorn:
build: .
image: gunicorn:20.1.0
container_name: gunicorn
volumes:
- .:/usr/src/app/
- gunicorn:/var/run/gunicorn
env_file: docker.env
stdin_open: true
tty: true
nginx:
image: nginx:1.17.7
container_name: nginx
depends_on:
- gunicorn
ports:
- "80:80"
volumes:
- ./gunicorn.conf:/etc/nginx/conf.d/default.conf
- ./static_root:/var/www/mysite/static
- gunicorn:/var/run/gunicorn
volumes:
gunicorn:
driver: local
upstream gunicorn-django {
server unix:///var/run/gunicorn/gunicorn.sock;
}
server {
listen 80;
server_name localhost;
location / {
try_files $uri @gunicorn;
}
location /static/ {
root /var/www/mysite;
}
location @gunicorn {
proxy_pass http://gunicorn-django;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
DJANGO_SECRET_KEY='XXXXX'
ALLOWED_HOSTS='example.com'
# 開発環境の場合は、ALLOWED_HOSTS='localhost 127.0.0.1'
起動コマンド
docker-compose upコマンドでコンテナを生成・起動する。
localhost
にアクセスし画面が出ればOK
$ docker-compose up -d