Django を Nginx コンテナと uWsgi で動かしてみる

今まで Nginx は VPS に直で入れてしか使った事なかったので、Nginx のコンテナを試してみたいと思います。

とりあえず Nginx コンテナから Django コンテナにつないで Hello Simple Django とか表示してみたいと思います。

参考

階層

階層は下の通りです。
settings ファイルを本番とローカルとで分けているのでそこだけ注意ですが、ファイルを分ける方法は本題ではないので、ここでは書かないことにします。

.(project)
├── backend
│   ├── config
│   │   ├── asgi.py
│   │   ├── settings
│   │   │   ├── base.py
│   │   │   ├── local.py
│   │   │   └── production.py
│   │   └── wsgi.py
│   ├── manage.py
│   └── templates
│       └── app
│
├── nginx
│   ├── default.conf
│   └── uwsgi_params
│
├── docker-compose.yml
├── dockerfile
└── requirements.txt

docker のファイルを作成する

まずは dockerfile から。
requirements.txt を使ってインストールしていますが、この中に uWsgi を記載しておきます。
このイメージから、django 用のコンテナを作成します。

FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /project
WORKDIR /project
ADD requirements.txt /project/
RUN pip install -r requirements.txt
ADD . /project/
EXPOSE 8000

一応 requirements.txt は次の通りです。

asgiref==3.5.1
backports.zoneinfo==0.2.1
Django==4.0.4
mysqlclient==2.1.0
sqlparse==0.4.2
uWSGI==2.0.20

docker-compose は次の通りです。

version: "3"
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
  web:
    build: .
    tty: true
    working_dir: /project
    command: uwsgi --socket :8000 --module config.wsgi --chdir /project/backend
    ports:
      - 8000:8000
    volumes:
      - .:/project
    depends_on:
      - db
  db: ...(略)...

後ほど作成する Nginx の設定ファイルを volumes して Nginx のコンテナ使用できるようにします。

volumes:
  - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
  - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params

django のコンテナ内で uwsgi を実行して Nginx からの通信を受け取れるように起動しておきます。

command: uwsgi --socket :8000 --module config.wsgi --chdir /project/
  • --module

    • wsgi ファイルまでのパスを指定しています。
  • --chdir

    • backend が django プロジェクトになるので backend までのパスを指定しています。
    • (ちなみに 「bash -c "cd ./backend/ && uwsgi --socket..."」とか出来ないようです。)

nginx のファイルを作成する

default.conf です。
server web:8000 の web の部分は、django が入っているコンテナ名を指定してあげています。

upstream django {
    ip_hash;
    server web:8000;
}
server {
    listen 80;
    server_name localhost;
    location / {
        uwsgi_pass django;
        include /etc/nginx/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;

Django の設定

settings 今回の場合は production.py になりますが、ALLOWED_HOSTS の許可も忘れずにします。

ALLOWED_HOSTS = ['*']
YouTube