Help us understand the problem. What is going on with this article?

Django2環境をDocker使って整える

はじめに

興味本位で新しいフレームワークを試してみようと始めた『Laravel環境構築

Docker構築にも慣れてきたので
改めてDjango2環境の開発環境としてDockerで作成してみました。

環境

  • Windows10 Pro
  • docker for windows (docker desctop community) (ver.2.1.0.2)
  • VSCode

Django2環境

Dockerの構成はこんな感じ

nginx-python-postgres.png

  • django2_nginx:1.17.3 (based nginx:1.17.3)
  • django2_python:3.7.4 (based python:3.7.4)
  • django2_postgres:9.6.15 (based postgres:9.6.15)

dockerの定義

ローカルのディレクトリ構成はこんな感じにしました。

├─ laravel/
   ├─ postgres/
   │  └─ Dockerfile       # postgres用Dockerfile
   ├─ nginx/
   │  ├─ etc/
   │  │  ├─ conf.d/
   │  │  │  └─ default.conf    # nginxサイト定義
   │  │  └─ nginx.conf          # nginx基本定義
   │  └─ Dockerfile               # nginx用Dockerfile
   ├─ python/
   │  ├─ apps/
   │  │  │ :
   │  │  └─ setup.sh    # migrate,createsuperuser用スクリプト
   │  └─ Dockerfile      # php-fpm用Dockerfile
   ├─ .gitignore           # pythonのキャッシュ除外用gitignore
   ├─ docker-compose.yaml  # 全てのdocker定義

docker-compose.yaml

全ての要、docker-compose.yamlはこんな形になりました。
ポートが微妙におかしいのは、先日のLaravevlと共存したいためです(笑)

  • nginxはポート8088でlistenしています。
  • nginxはdjango2プロジェクトのapps/static/opt/apps/staticに腹持ちさせました。
  • postgresは5432番でlistenしています。
  • postgresはデータ永続化のためdbvolumeコンテナを作成しました。
  • pythonは/opt/appsにdjango2プロジェクトをあらかじめ生成したものを腹持ちさせています。
  • Django2はgunicornによりnginxからの通信を3031番で待ち受けします。
docker-compose.yaml
version: '3.3'
services:
  postgres:
    container_name: django2_postgres
    build: ./postgresql/
    image: django2_postgres:9.6.15
    restart: always
    ports:
      - 5432:5432
    volumes:
      - dbvolume:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=sample_db
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres@1234
      - PGDATA=/var/lib/postgresql/data

  python:
    container_name: django2_python
    build: ./python/
    image: django2_python:3.7.4
    links:
      - postgres
    volumes:
      - ./python/apps:/opt/apps
      - ./python/app/static:/opt/apps/static
    expose:
      - 3031
    environment:
      - DJANGO_ADMIN_USER=admin
      - DJANGO_ADMIN_EMAIL=admin@localhost.localdomain
      - DJANGO_ADMIN_PASSWORD=django2@1234
    command: >
      /bin/bash -c
      "./setup.sh && 
       gunicorn wsgi -b 0.0.0.0:3031"
    depends_on:
      - postgres

  nginx:
    container_name: django2_nginx
    build: ./nginx/
    image: django2_nginx:1.17.3
    ports:
      - 8088:80
    links:
      - python
    depends_on:
      - python
    volumes:
      - ./python/app/static:/opt/apps/static

volumes:
  dbvolume:

それでは各Dockerの定義を見ていきましょう!

postgres:9.6.15用Docker定義

TZ変更のみのDockerfileとしています。

postgres/Dockerfile
FROM postgres:9.6.15

RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

nginx:1.17.3用Docker定義

TZ変更およびログファイルのstdout,strerrリンク、設定ファイルのCOPYをするDockerfileとしています。

nginx/Dockerfile
FROM nginx:1.17.3

RUN ln -sf /usr/share/zoneinfo/Japan /etc/localtime

RUN ln -sf /dev/stdout /var/log/nginx/access.log && \
    ln -sf /dev/stderr /var/log/nginx/error.log && \
    ln -sf /dev/stdout /var/log/nginx/host.access.log

COPY ./etc/nginx.conf /etc/nginx/nginx.conf
COPY ./etc/conf.d /etc/nginx/conf.d

nginx.confの設定は、gzip、upstreamサーバ設定を行っています。

nginx/etc/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log debug;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    server_tokens off;

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_types image/png image/gif image/jpeg text/javascript text/css;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_comp_level 9;

    upstream django2_server  {
        server python:3031 fail_timeout=0;
    }

    include /etc/nginx/conf.d/*.conf;
}

default.confの設定は割とシンプル

nginx/etc/conf.d/default.conf
server {
    listen       80;
    server_name  _;

    root /opt/apps;
    index index.php;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;

    location /static/ {
        root /opt/apps/static;
    }

    location / {
        try_files $uri @proxy_to_django2;
    }

    location @proxy_to_django2 {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
        proxy_pass http://django2_server;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\. {
        deny  all;
    }
}

python:3.7.4用Docker定義

TZ変更は他サーバーのDockerfileと同様ですが、
pythonモジュールのインストールをrequirements.txtにより指定し行っています。

WORKDIRはDjango2プロジェクトのappsフォルダとしています。

python/Dockerfile
FROM python:3.7.4

ENV APP_PATH /opt/apps

RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

WORKDIR $APP_PATH

COPY ./apps/requirements.txt $APP_PATH/

RUN pip install --no-cache-dir -r $APP_PATH/requirements.txt

インストールするモジュールは以下の通りです。
作成するプロジェクトに応じて追加してください。

python/apps/requirements.txt
django==2.2.5
djangorestframework
django-filter
psycopg2
gunicorn

このsetup.shによりDBのマイグレーションおよびスーパーユーザ作成を行っています。
ユーザ名、メールアドレス、パスワードはdocker-compose.yamlの環境変数で指定しています。

python/apps/setup.sh
#!/bin/bash

echo "##### setup django2 app #####"
echo "-> migrate database"
python manage.py makemigrations --noinput
python manage.py migrate --noinput

echo "-> create super user"
python manage.py shell <<EOF
from django.contrib.auth.models import User
if not User.objects.filter(username='$DJANGO_ADMIN_USER'):
    User.objects.create_superuser('$DJANGO_ADMIN_USER', '$DJANGO_ADMIN_EMAIL', '$DJANGO_ADMIN_PASSWORD')
    print('    create super user: $DJANGO_ADMIN_USER')
else:
    print('    user: $DJANGO_ADMIN_USER already exists, nothing to do')

pythonが動作した際に作成されるキャッシュ達をgitにcommmitしないためのおまじない(^^♪

python/.gitignore
__pycache__/
*.py[cod]

Dockerの起動

ここまで準備ができたらdockerを起動します。

C:\Users\tak>cd C:\Git\docker\django2
C:\Git\docker\django2>docker-compose build
C:\Git\docker\django2>docker-compose up

いやDockerによる開発環境、手軽に作れて壊せて便利ですね!

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away