nikkie-ftnextの日記

イベントレポートや読書メモを発信

イベントレポート | #モグモグDjango にてDockerでDjango+MySQLの環境構築の知見を得ました

はじめに

いつも心は虹色に! nikkieです。
#モグモグDjango にお邪魔してDockerでDjango+MySQLの環境を構築するノウハウをつかみました。

勉強会の概要

第2回 モグモグDjango - connpass

Djangoもくもく会 モグモグDjango を開催します. Django初心者の方から,上級者の方までどなたでもご参加下さい(^^)
この会では,しーーっんとしているもくもく会ではなく,質問や分からないところがあったら,その場で聞くことができる環境にしたい!と思っています.

7月に続いて2回目開催の#モグモグDjango
『現場で使える基礎Django』や加筆版(Kindle版ペーパーバック版)の著者akiyokoさんが今回もいらっしゃり、Djangoユーザにとって充実のもくもく環境でした。

休憩の王道ドーナツ(mamixさん持参)もあり、上質な甘さを堪能していました。(本当に美味しかった。。ごちそうさまでした)

取り組んだこと

Django Girls Tutorial翻訳でお世話になっているkaizumakiさんが、前回からDockerでDjango+MySQLの環境を構築するのに取り組まれていたので、一緒に調べていました。

本当はやりたいことを用意していたのですが、業務がオーバーフローしてしまい、何をするかが詰められないままの参加でした。1(ここは要反省です。。)

Django+MySQLの環境構築で得られた知見

以下のブログをベースに取り組みました。2

以下の2つの点が収穫です。

  • PyMySQLが必要
  • db-datadirというディレクトリをホスト側に作って、MySQLのデータを永続化する

わかったことをまとめていきます。

実行環境

  • macOS 10.13.6
  • Docker Client/Server 18.06.1-ce

Dockerfile

Dockerの公式ドキュメントの書き方が納得できないので、以下のように修正しました。

FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
  • Python3.6系を使うためベースイメージを変更(FROM命令)
  • ファイルやフォルダの単なるコピーであれば、ADD命令よりCOPY命令のほうが好ましいと認識しているので、COPY命令を使用

requirements.txt

Django~=2.0.6
PyMySQL
  • Django Girls Tutorialと同様に2.0系の最新を指定
  • Dockerの公式ドキュメントにあるpsycopg2PostgreSQL接続用3

docker-compose.yml

version: '3'

services:

  # https://hub.docker.com/r/mysql/mysql-server/
  db:
    image: mysql/mysql-server:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=P@ssw0rd
      - MYSQL_ROOT_HOST=%
    volumes:
      - ./db-datadir:/var/lib/mysql
      - ./sql:/docker-entrypoint-initdb.d

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
  • ホストからdbコンテナの3306ポートにアクセスしないだろうとdbにportsは設定していません(コンテナ間はDockerのネットワークで通信できる認識)
  • webコンテナにdepends_on設定しているので、webの方がdbより先に立ち上がることはないと考え、commandのsleep 3;は削除しました
  • volumesの./db-datadir:/var/lib/mysqlという書き方でMySQLのデータが永続化できることを初めて知りました。ホスト側にdb-datadirディレクトリができて、データが永続化されます。
    • これまでは以下のように宣言したdb-volumeを指定してきました。(関連箇所を抜粋)
services:
  db:
    volumes:
      - db-volume:/var/lib/mysql
volumes:
  db-volume:

参考記事ではsqlファイルを作成しているのですが、よくわからなかった私はスキップして先に進みました(注意: ハマりたくなければ、スキップしないでください)。

フォルダ構成

  • Dockerfile
  • requirements.txt
  • docker-compose.yml

プロジェクト作成

$ docker-compose up -d db
$ docker-compose run web django-admin startproject mysite .
$

フォルダ構成

  • db-datadir/
  • mysite/
  • manage.py
  • Dockerfile
  • requirements.txt
  • docker-compose.yml

[ハマった] DBの接続設定をして、migrationを実施

mysite/settings.pyを以下のように変更

import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'USER': 'django',
        'PASSWORD': 'P@ssw0rd_django',
        'HOST': 'db',
        'OPTIONS': {
            'charset': 'utf8mb4',
        },
    }
}
  • PORTは指定不要の認識です(デフォルトで3306ポートと通信している認識です)

webコンテナで プロジェクトを作成しよう! · Django Girls Tutorial にならってコマンドを実行させました。

$ docker-compose run web python manage.py migrate
 :
django.db.utils.OperationalError: (1045, "Access denied for user 'django'@'172.19.0.3' (using password: YES)")
$

djangoユーザでMySQLに接続できず落ちます。

現状の問題4

  • MySQLdjangoデータベースが作成されていない
  • MySQLdjangoユーザが作成されていない

これはsqlを作成して実行していないことが原因です。
必要なsqlを作成していきます。

DB初期化用SQLファイル作成 + 初期化実施

sql/001_setup_application_database.sql

CREATE DATABASE IF NOT EXISTS django CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'django'@'%' IDENTIFIED BY 'P@ssw0rd_django';
GRANT ALL PRIVILEGES ON django.* TO 'django'@'%';

フォルダ構成

  • db-datadir/
  • mysite/
  • sql/
  • manage.py
  • Dockerfile
  • requirements.txt
  • docker-compose.yml

sqlファイル作成後にdocker-compose up -d dbをしても、初期化は実施されません。
データを永続化しているdb-datadirディレクトリを削除する必要がありました。5
(参考記事中の「DBを作成し直す場合の手順」をもとにしました)

$ docker-compose down
$ rm -rf db-datadir
$ docker-compose up -d db
$ docker-compose run web python manage.py migrate
$

dbコンテナが立ち上がるまで少し時間を置く必要がありましたが、これでデータベースとユーザが作られ、マイグレーションが実行できました。
sqlファイルにより、手動でデータベースやユーザを作る作業をなくしているんだなと気づきました。

superuser作成

$ docker-compose run web python manage.py createsuperuser
 :
$

以上で設定が終わったのでdocker-compose up -dしてから、http://127.0.0.1:8000/adminにアクセスすると。。

f:id:nikkie-ftnext:20180908205552p:plain

管理画面にログインできました^ ^

他に情報提供したこと

  • Docker関連でもう1件サポート: ポートの設定が食い違っていました
    • runでポート設定を8000:8000と指定
    • コンテナに接続してから0.0.0.0:8080でrunserver
  • k8sでデプロイされる方がいらっしゃったので、知っている情報を提供
    • 無事デプロイできたそうでおめでとうございます!

成果発表から

興味深かった情報を挙げていきます。

  • 男性OKのPyLadies Event PyLadies Tokyo - 4周年記念パーティ - connpass
    • 10/8の技術書典と重なるのですが、LTドリブンでなにかやりたかったので申し込んでみました
  • 年内いっぱい応募期間だそうで、力試ししてもいいかも Urban Data Challengeアーバンデータチャレンジ
  • どりらんさんのPyConトーク「Jupyterで広がるPythonの可能性」の頭出し。Jupyterのマジックコマンドすごかった
  • akiyokoさんの新刊応用編はすごくほしい内容でした。技術書典全体で見ると3冊程度Django本があるらしい?
  • 懇親タイムで OSS Gate | Doorkeeper 教えていただきました。ありがとうございます。駆け出しの身でも、コードでなくて翻訳でも、貢献できるそうなので、飛び込んでみよう!

感想

独学してきたDockerでお役に立てて嬉しく思います。
人に教えると自分の学びにもなるんですよね(データ永続化の理解が進みました!)。
一緒に考えるスタンスで、たまった知見を引き続き共有していきます。

今回「Pythonもくもく会でAzureでハマっている人」という通り名を得ました。
言い得て妙ですね。笑
まだまだハマる日々は続きそうですので、温かい目で見守っていただけると幸いです。

次回も予定されているそうで非常に楽しみです(akiyokoさんの新刊でもくもく予定です)。
皆さん、どうもありがとうございました!

脚注


  1. 月曜日から5営業日、勤務先のブログをVPSWordPressで構築していました。7日(金)の夜に設定漏れが見つかり、もくもくの時間の一部を使って対応させていただきました。。

  2. Dockerの公式ドキュメント Quickstart: Compose and Django | Docker DocumentationMySQL版とのことです。助かりました。ありがとうございます!

  3. ここはkaizumakiさんの疑問で調べたため、つまずかずに済みました(私は書いてあっても問題ないだろうと先走っていました)。ありがとうございました。

  4. docker exec -it <dbコンテナ> bashしてからrootユーザでmysqlに接続し、突き止めました

  5. docker-compose build dbで再ビルドしてもデータベースとユーザが作られず、同様のエラーでした