DockerでDjangoの開発環境を作成する(Quickstart: Compose and DjangoのMySQL版)
はじめに
Dockerの公式ページにDocker Composeを使った簡単なDjango/PostgreSQLの環境構築のチュートリアルがあります。
普段からMySQLを使うことが多いので、PostgreSQLの代わりにMySQLを使ってチュートリアルをやってみました。
環境
- OS: Fedora 26
- Docker: Docker version 1.13.1, build b5e3294/1.13.1
- Docker Compose: docker-compose version 1.16.1, build 6d1ac219
- MySQL設定
元ネタと違う点
- データベースをPostgreSQLからMySQLに変更しています。
- Python実行環境のイメージをデフォルトからalpineに変更しています。
手順
プロジェクト用ディレクトリの作成と移動
適当なプロジェクト用ディレクトリを作成します。
$ mkdir -p ~/working/docker_test/django_mysql $ cd ~/working/docker_test/django_mysql
各種ファイル作成
Dockerfile
$ cat <<EOF > Dockerfile FROM python:3-alpine ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code ADD requirements.txt /code/ RUN pip install -r requirements.txt ADD . /code/ EOF
requirements.txt
$ cat <<EOF > requirements.txt Django>=1.8,<2.0 PyMySQL EOF
DB初期化用SQLファイル
$ mkdir sql $ cat <<EOF > 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'@'%'; EOF
docker-compose.yml
dbコンテナの起動前にDjango開発サーバが起動してしまうことがあったため、webコンテナのcommandにsleepを追加しています。
$ cat <<EOF > 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 ports: - "3306:3306" web: build: . command: sh -c "sleep 3; ./manage.py runserver 0.0.0.0:8000" volumes: - .:/code ports: - "8000:8000" depends_on: - db EOF
DBの初期化
dbコンテナをバックグランドで起動して、MySQLのデータベースを初期構築します。
このとき、コンテナ側の/var/lib/mysqlにホスト側の./db-datadirがマッピングされ、db-datadirが空であれば初期化されてMySQLデータディレクトリ相当のファイルが生成されます。
$ docker-compose up -d db $ ls -al db-datadir
元ネタのチュートリアルでは、この段階ではdbコンテナは起動しておらず、次のDjangoプロジェクト作成時にwebコンテナと一緒に起動させています。
しかし、今回はMySQLを利用して初回起動後にデータベースやユーザを作成したりMySQLの起動に時間がかかることもあり、webとdbを一緒に初回起動してしまうとDjangoからMySQLへの接続に失敗してしまうことがあったため、先にdbコンテナだけ起動させています。
Djangoプロジェクトの作成
webコンテナを起動して、Djangoプロジェクトを作成します。
$ sudo docker-compose run web django-admin.py startproject mysite .
私の環境ではsudoをつけないとwebコンテナビルド時にエラーで失敗してしまいました。 下記が発生したエラーの内容です。
Building web ERROR: Error processing tar file(exit status 1): time="2017-11-04T17:24:03+09:00" level=info msg="SUSE:secrets :: enabled" unexpected EOF
権限の変更
コンテナ側で作成されたMySQLのデータディレクトリやDjangoプロジェクトのファイルはrootユーザで作成されるため、所有者をホスト側のユーザに変更します。
$ sudo chown -R $USER:$USER mysite manage.py
MySQLのデータディレクトリにマッピングするdb-datadirも含めて所有者を変更してしまうと、DjangoからMySQL接続する際に下記のエラーが発生しますので注意してください。
django.db.utils.InternalError: (1018, "Can't read dir of './django/' (errno: 13 - Permission denied)")
settings.py の編集
webコンテナ内のDjangoプロジェクトからdbコンテナ内のMySQLに接続するために、settings.pyのDATABASESを書き換えます。
$ vi 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', 'PORT': 3306, 'OPTIONS': { 'charset': 'utf8mb4', }, } } ---
DBマイグレーション
Djangoのデフォルトアプリケーションのテーブルを作成します。 デフォルト以外のアプリケーションが追加されていないのであれば、makemigrationsは不要です。
$ docker-compose run web ./manage.py makemigrations $ docker-compose run web ./manage.py migrate
管理者ユーザの作成
Django管理サイトにログインするためのスーパーユーザを作成します。
$ docker-compose run web ./manage.py createsuperuser --username admin --email admin@localhost [自動化する場合] $ docker-compose run web ./manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@localhost', 'admin')"
Django開発サーバの起動
webコンテナをdocker-composeで起動し、Djangoの開発サーバを起動します。
$ docker-compose up -d
ブラウザで動作確認
下記URLにアクセスして、作成したスーパーユーザで管理サイトにログインできることを確認します。
その他参考手順
バックグラウンドで起動したコンテナの出力を確認
フォアグラウンドで起動した際に出力されるログを表示させます。
[すべてのコンテナ] $ docker-compose logs -tf [webのみ] $ docker-compose logs -tf web [dbのみ] $ docker-compose logs -tf db
DBを作成し直す場合の手順
$ docker-compose down $ sudo rm -rf db-datadir $ docker-compose up -d db $ docker-compose run web ./manage.py makemigrations $ docker-compose run web ./manage.py migrate $ docker-compose run web ./manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@localhost', 'admin')" $ docker-compose up -d
Dockerコンテナ、イメージ削除一括方法
$ docker container rm $(docker container ls -q) $ docker image rm $(docker image ls -q)
まとめ
Dockerの公式ページのDjangoチュートリアルのMySQL版をやってみました。
次は、ApahceかNginxでプロキシサーバを追加し、uWSGIでDjangoを起動させてよりプロダクション環境に近い構成を作ってみたいと思います。