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\ としたが、違う名前を使っても以降の記述はそのまま使えるはず。
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 設定のファイル。
特に書き換える必要がないとされていて、ネット上でも「こう書いておけばいいのだ」とスルーされている。
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 のバージョンを非表示にする。
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 とした。
GRANT ALL PRIVILEGES ON test_sakura TO 'sumire'@'%';
FLUSH PRIVILEGES;
requirements.txt
requirements.txt を使うと、pip で指定のパッケージを一括してインストールすることができる。
バージョンを省略すると最新版が入る。
検証に使ったバージョンは 2020/03 時点のもの。
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 で読み込む。
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 のファイル全体
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 を編集する。
ALLOWED_HOSTS = ["*"]
データベースの切り替え
エラーが出なかったら、次にデータベースをデフォルトの sqlite から MySQL に切り替えるために django\src\mysite\mysite 内の stttings.py を変更する。もともとは PyMySQL を使用していたが、いまは mysqlclient の方が標準らしいのでそうする。データベースの指定をする記述があるので、それを次のように置き換える。ユーザー sumire とパスワード akutagawa を指定して、データベース sakura にアクセスできるようにする。
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'
を追加
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'))
を追加
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 アプリケーションが見える。
おわり