Breaking News

Default Placeholder Default Placeholder

以前の記事で Djangoの開発環境をdocker-composeで構築したのですが、結局本番環境ではNginxを使うということでローカル環境のNginxを使っての構築方法をまとめました。

やりたいこと

ブラウザで localhostでDjangoアプリケーションにアクセスできるようにしたい。

内部の処理の流れ

内部の処理の流れは下記のようになります。

localhostでアクセス(portは80) -> nginxからポート 8001 を通じて djangoコンテナにアクセス -> djangoコンテナで起動している uwsgiのソケットにアクセス -> アプリケーションにアクセス

requirements.txt

uwsgiを追加します。

# requirements.txt
uwsgi # ←追加

nginx

docker/nginx/Dockerfile

nginx用のDockerfileを作成します。

# nginx/Dockerfile
FROM nginx:1.15.8-alpine
# 設定ファイルをイメージ内にコピー
ADD app.conf /etc/nginx/conf.d/app.conf
# コンテナ起動時にNginxを起動する
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

docker/nginx/app.conf

nginxの設定ファイルを作成します。

# nginx/app.conf
upstream django {
    ip_hash;
    server django:8001;
}
server {
    listen      80;
    server_name localhost;
    charset     utf-8;
    location /static {
        alias /static;
    }
    location / {
        uwsgi_pass  django;
        include     /etc/nginx/uwsgi_params;
    }
}
server_tokens off;

docker/nginx/uwsgi_params

uwsgiの変数用の設定ファイルを作成します。

# nginx/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

Dockerfile

# Dockerfile
FROM python:3.7.4-alpine3.10
ENV PYTHONUNBUFFERED 1
ENV APP_PATH /opt/apps
WORKDIR $APP_PATH
ADD . $APP_PATH/
RUN apk add --no-cache gcc libc-dev linux-headers
RUN pip install --no-cache-dir -r $APP_PATH/requirements.txt

docker-compose.yml

docker-compose.ymlでコンテナを繋げてみましょう。

# docker-compose.yml
version: '3.7'
services:
  django:
    restart: always
    build: .
    volumes:
      - ./:/opt/apps
      - ./static:/static
    depends_on:
      - db
      - redis
    command: ['sh', 'launch.sh']
    expose:
      - "8001"
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: app
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: QXxHJS9C9lUK
    tty: true
    ports:
      - 3306:3306
    command: mysqld --character-set-server=utf8mb4 --explicit_defaults_for_timestamp=true
  redis:
    image: redis:latest
    ports:
      - 6379:6379
    tty: true
  nginx:
    build: ./docker/nginx/
    volumes:
      - ./static:/static
    ports:
      - "80:80"
    depends_on:
      - django

launch.sh

起動スクリプトを作成します。

pip install -r requirements.txt
python manage.py migrate
uwsgi --socket 0.0.0.0:8001 --module app.wsgi

最後の行の app.wsgiのappの部分は、wsgi.pyファイルが生成されたディレクトリ名を入れてください。

起動してみる

さて、まずイメージ作成してみましょう。

$ docker-compose build --no-cache

続けてコンテナ起動します。

$ docker-compose up

下記のような出力がされたら成功です。

django_1  | WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x5635814e5ee0 pid: 12 (default app)
django_1  | uWSGI running as root, you can use --uid/--gid/--chroot options
django_1  | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
django_1  | *** uWSGI is running in multiple interpreter mode ***
django_1  | spawned uWSGI worker 1 (and the only) (pid: 12, cores: 1)