LoginSignup
8
15

More than 3 years have passed since last update.

Docker + django + Nginx + MySQL を理解する

Last updated at Posted at 2020-03-19

2020-03-27: Windows 10 Professional/Docker Desktop 2.2.0.4/docker-commpose 1.25.4

Django + Nginx + MySql で開発環境を作るための情報。
Qiita 内に優れた記事があり、その通りやれば動くのだが、何をやっているのかよく分からなかったので調べた。

参考サイト
https://qiita.com/kenkono/items/6221ad12670d1ae8b1dd

注意すべき落とし穴

  • AWS のサーバーを使うときはセキュリティグループの設定に注意
  • MySQL の初期設定をするときは、ユーザー名やパスワードは相互に矛盾がないようにする
  • docker-compose はいきなり up せず、build してからソースの手直しがいる
  • MySQL の 8.0 は新しい認証方式への対応が複雑なので、5.7 のままにしておくのが吉

まず Windows 側での作業ディレクトリの準備

概要

c:\Local 以下にこういうディレクトリ構造を作成。
全体を入れるディレクトリの名前は c:\Logal\projectname\ としたが、違う名前を使っても以降の記述はそのまま使えるはず。

c:\Local
projectname\
    backup\
    mysql\
    nginx\
        conf\
            app_nginx.conf
        log\
        uwsgi_params
    python\
        Dockerfile
        requirements.txt
    sql\
        init.sql
    src\
    static\
    docker-compose.yml
ディレクトリ名 内容 格納するファイル
projectname docker 用の全体ディレクトリ 直下に docker-compose.yml を格納
projectname\backup MySQL バックアップデータ mysqldump でダンプしたデータのやり取りするために使用
projectname\mysql MySQL データ 初期は空。MySQL がデータを保存するディレクトリ。
projectname\nginx Nginx 設定用ファイル uwsgi_params を格納
projectname\nginx\conf Nginx 設定用ファイル Nginx のメイン設定ファイル app_nginx.conf を格納
projectname\nginx\log Nginx ログ 初期は空。Nginx のログが作られる。
projectname\python dockerfile と requirements.txt を格納
projectname\sql MySQL 初期化ファイル MySQL の初期化用設定ファイル init.sql を格納
projectname\src django のソース 初期は空。jango のプロジェクトディレクトリ。この直下にアプリのフォルダを置く
projectname\static Web の静的ページ用 静的な HTML ファイルを入れる

準備するファイル

uwsgi_params

wsgi(Web Server Gateway Interface)は、Python で Web サーバーと Web アプリケーションをつなぐインターフェース。
uwsgi_params は Nginx用 の wsgi 設定のファイル。
特に書き換える必要がないとされていて、ネット上でも「こう書いておけばいいのだ」とスルーされている。

projectname\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;

app_nginx.conf

Nginx のメインの設定ファイル。
upstream で、django のサーバーを指定する。
server はドメイン名か IP アドレスとオプションでポートを指定する。
location では /static には静的コンテンツを入れる。url を変える場合は /web という部分を書きかえる。2 つ目の location の記述によって、nginx にアクセスのあった static を除くすべての情報 wsgi 経由で Django へ行く。
access_log はアクセスログを標準的なフォーマット(main)で出力する。
error_log はエラーログを出力する。
server_tokens off; はエラーページに nginx のバージョンを非表示にする。

projectname\nginx\conf\app_nginx.conf
upstream django {
    ip_hash;
    server python:8001;
}

server {
    listen      8000;
    server_name 127.0.0.1;
    charset     utf-8;

    location /web {
        alias /static;
    }

    location / {
        uwsgi_pass  django;
        include     /etc/nginx/uwsgi_params;
    }
}

access_log  /var/log/nginx/access.log main;
error_log  /var/log/nginx/error.log warn;

server_tokens off;

init.sql

docker の MySQL image は、/docker-entrypoint-initdb.d/ にあるスクリプトを使って、最初に image を起動したときの初期化が行える。django で使用するデータベース名(後述)が sakura だと、テスト用のデータベースは test_sakura となる。ここではユーザー名を sumire とした。

projectname\sql\init.sql
GRANT ALL PRIVILEGES ON test_sakura TO 'sumire'@'%';

FLUSH PRIVILEGES;

requirements.txt

requirements.txt を使うと、pip で指定のパッケージを一括してインストールすることができる。
バージョンを省略すると最新版が入る。
検証に使ったバージョンは 2020/03 時点のもの。

projectname\python\requirements.txt
Django==3.0.4
uwsgi==2.0.18
mysqlclient==1.4.6

dockerfile

ENV PYTHONUNBUFFERED 1は、バッファがたまってから出力するのを避ける指定。
RUN 命令は既存イメージ上でコマンドを実行し、その結果得られたイメージは Dockerfile の次のステップで使われる。
WORKDIR 命令は Dockerfile で次の行の ADD の実行時の作業ディレクトリの指定。
もし WORKDIR が存在しなければディレクトリを作成する。
ADD は requirements.txt に書かれたものを pip で読み込む。

projectname\python\dockerfile
FROM python:3.8.2
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

docker-compose.yml

docker-compose の本体の設定ファイル。Nginx と MySql と Python+Django の 3 つの設定と連携について定義する。
YAML ファイルのインデントはスペース 2 個単位で行わないと、エラーが出ることに注意。

Nginx 記述部

nginx というのがサービス名。それぞれのサービスに個別にアクセスしたくなったときに必要となる。
この例ではポート番号は 8000 になっているが、本番用の 80 にしたい場合は、"8000:8000" を "80:8000" に変更する。
volume はローカル側のフォルダをコンテナ内にマウントする指定。ホスト(Windows)のディレクトリ:コンテナ内のディレクトリ、の書式。
environment の TZ はタイムゾーンで、これをやっとかないとログの時計が標準時になってしまう。

db 記述部

db というのがサービス名。
environment でデータベースの基本情報を記述。データベース名は sakura で、ユーザー名は sumire としてある。MySQL の root と sumire のパスワードの指定も行う。
volume はローカル側のフォルダをコンテナ内にマウントする指定。Windows 側の mysql フォルダと同期して永続化する。

python 記述部

python というのがサービス名。
command は uwsgi を使用してポート 8001 を開放。app.wsgi の app は Django のプロジェクト名で、django-admin startproject app の app部分。--py-autoreload 1 は Django アプリ開発の際に、ファイル等に変更があった際は自動リロードする。--logto /tmp/mylog.log はログを残す指定。

docker-compose.yml のファイル全体

projectname\docker-compose.yml
version: '3'

services:
    nginx:
        image: nginx:1.16
        ports:
            - "8000:8000"
        volumes:
            - ./nginx/conf:/etc/nginx/conf.d
            - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
            - ./nginx/log:/var/log/nginx
            - ./static:/static
        depends_on:
            - python
        environment:
            TZ: 'Asia/Tokyo'

    db:
        image: mysql:5.7
        command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
        ports:
            - "3306:3306"
        environment:
            MYSQL_ROOT_PASSWORD: natsume
            MYSQL_DATABASE: sakura
            MYSQL_USER: sumire
            MYSQL_PASSWORD: akutagawa
            TZ: 'Asia/Tokyo'
        volumes:
            - ./mysql:/var/lib/mysql
            - ./sql:/docker-entrypoint-initdb.d
            - ./backup:/var/lib/backup

    python:
        build: ./python
        command: uwsgi --socket :8001 --module app.wsgi --py-autoreload 1 --logto /tmp/mylog.log
        volumes:
            - ./src:/code
            - ./static:/static
        expose:
            - "8001"
        depends_on:
            - db
        environment:
            TZ: 'Asia/Tokyo'

イメージのダウンロードとコンテナ作成、設定

ここまでの時点で作成した django フォルダのバックアップを取っておくと、このあと各イメージのバージョンが合わないなどの不具合があったときに、やり直しが早く済む。

インストールと docker-compose の実行

新しく作るプロジェクトの名前を app とする。
projectname\ で以下のように docker-compose を実行する。
実行するときカレントディレクトリを間違えると謎のエラーが連発するので注意。

docker-compose build
docker-compose run python django-admin.py startproject app .

ALLOWED_HOSTS の追加

新しいバージョンの django は ALLOWED_HOSTS の記述が必要。settings.py を編集する。

projectname\src\app\settings.py
ALLOWED_HOSTS = ["*"]

データベースの切り替え

エラーが出なかったら、次にデータベースをデフォルトの sqlite から MySQL に切り替えるために django\src\mysite\mysite 内の stttings.py を変更する。もともとは PyMySQL を使用していたが、いまは mysqlclient の方が標準らしいのでそうする。データベースの指定をする記述があるので、それを次のように置き換える。ユーザー sumire とパスワード akutagawa を指定して、データベース sakura にアクセスできるようにする。

projectname\src\app\settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'sakura',
        'USER': 'sumire',
        'PASSWORD': 'akutagawa',
        'HOST': 'db',
        'PORT': '3306',
    }
}

マイグレーション

projectname\ で以下のコマンドを実行する。
実行時のカレントディレクトリを間違えると謎のエラーに悩まされるので注意。
データベースの変更を django に知らせて反映させる。
データベースのバージョンが合わなかったりするとエラーが出る。

docker-compose run python ./manage.py makemigrations
docker-compose run python ./manage.py migrate

管理者の設定

管理者のユーザー名とパスワードを設定する。
projectname\ で以下のコマンドを実行する。
ユーザー名はデフォルトで root となっている。まずは捨てパスでいいと思うが、あまりいい加減なパスワード(password など)を入力するとダメと言われるので注意。

docker-compose run python ./manage.py createsuperuser

コンテナの起動

docker-compose up -d

ブラウザで http://localhost:8000 にアクセスして Django のページが見えたら完成。停止は docker-compose stopで、起動はdocker-compose up -dで。

作成したソースの反映

新しいアプリを置き django の設定を更新

開発したアプリ(ここでは memo とする)をプロジェクトに入れる。フォルダ memo ごと projectname\src\ 下に置く。

新しいアプリのインストール

projectname\src\app\settings.py の INSTALLED_APPS に'memo.apps.MemoConfig'を追加

projectname\src\app\settings.py
INSTALLED_APPS = [
    'memo.apps.MemoConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

アプリの url を設定

projectname\src\app\urls.py にfrom django.urls import includeと、 url へのパスpath('memo/', include('memo.urls'))を追加

projectname\src\app\urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('memo/', include('memo.urls')),
    path('admin/', admin.site.urls),
]

変更をマイグレーションして django に認識させる

projectname\ で以下のコマンドを実行する。

docker-compose run python ./manage.py makemigrations
docker-compose run python ./manage.py migrate
docker-compose up -d

これでブラウザからhttp://localhost:8000/webで \static に置いた静的な html ファイルが見える。http://localhost:8000/memoで、memo アプリケーションが見える。

おわり

8
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
15