今回は、DjangoのREST framework
のローカル環境に挑戦してみました。
初めてPythonのフレームワークを触るので、浅はかなところもあるかと思いますがご了承下さい!
ゴールは、ブランチでこれが表示されるところまでいきます。
docker-composeを使用するので、インストールしてない方はインストールしましょう。
この記事ではインストールの説明は割愛します。(「docker for mac インストール」で検索すれば出てくると思います。)
さて、さっそく取り掛かっていきます。
※ 私の環境は、macOS
作業場作成
適当に今回のプロジェクトを作成するディレクトリに移動します。
$ cd /path/to/project
or
$ mkdir project_name
任意ですが、一応README.mdを作成。
今回、DB(mysql)と接続するために、初期データを置いておく必要があります。
$ mkdir mysql
$ cd mysql
$ mkdir init
上記を作成して、mysql/init/
というディレクトリを作成します。
このディレクトリ配下に、.sqlをファイルを置いて置きます。
※ この.sqlファイルですが、既存の運用で使用されているDBのdumpファイルでも可能です。
ちょっと試したいというかたは、テーブルを作成するsql文などを適当に記述してもOKです。
ここまでのプロジェクト構成は以下です。
<project_name>
├── README.md
├── mysql
│ └── init
│ └── test.sql
主要なファイルを作成
次にDockerfileとdocker-compose.ymlをプロジェクトディレクトリで作成します。
$ touch Dockerfile
$ touch docker-compose.yml
重要なのは、この2つのファイルの記述です。
FROM python:3.5
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
# install Libraries
COPY requirements.txt /code/
RUN pip install -r requirements.txt
# to be consistent versions of between "Django and PyMySQL"
RUN pip install -U PyMySQL
ADD . /code/
version: '3.0'
services:
db:
image: "mysql:latest"
container_name: <container_name>
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_DATABASE: <db_name>
MYSQL_ROOT_PASSWORD: <db_root_pwd>
MYSQL_USER: <db_user>
MYSQL_PASSWORD: <db_pwd>
ports:
- 3306:3306
volumes:
- type: bind
# source: ./docker/db/init.sql
source: ./mysql/init/<file_name>.sql
target: /docker-entrypoint-initdb.d/<file_name>.sql
- type: bind
source: /tmp/docker/tmpdata
target: /tmp/tmpdata
web:
container_name: <container_name>
build: .
command: python manage.py runserver 0.0.0.0:8080
volumes:
- .:/code
ports:
- 8080:8080
environment:
DJANGO_SECRET_KEY: $DJANGO_SECRET_KEY
DJANGO_DEBUBG: $DJANGO_DEBUBG
depends_on:
- db
ほとんど公式と同じ記述です。
ただ、公式では、PostgreSqlの場合ですし、先程作成したDBの記述はありません。
シンプルに詳細を確認したい人は、一読するといいと思います!
クイックスタート・ガイド:Docker Compose と Django — Docker-docs-ja 17.06.Beta ドキュメント
Dockerfile
こちらはシンプルですね。python ^3.5をベースにpipでrequirements.txtを元にライブラリをインストールさせています。
ここで一番注目したいのは、PyMySQL
のアップグレードです。
私が環境構築をしている時に、何時間もつまったのがこれ。
なんてことないエラーでしたが、どうもうまくいかなかった...
知っていればなんてことないことなのですが、どうやらDjangoのversionが2.0以上になって発生するエラーのようでした。
色々ググってみると、色んなやり方で解決されているみたいでしたが、アップグレード1発で解決されるのが一番シンプルですよね!
docker-compose.yml
こちらもいたって普通の記述です。
初期データを必要とすることで、volumes
の設定(特にtarget
)が重要です。
docker-entrypoint-initdb.d
に注目します。
これは、mysqlのイメージがコンテナの起動時に自動的に初期データを読み込んでくれる機能を使用しています。
下のbindは、初期データがなかった場合に代用できる記述です。
ここまで作成して、足りないファイルが2つあります。
requirements.txt
このプロジェクトで必要なPythonのライブラリを記述します。
Django==2.1.1
djangorestframework
django-filter
psycopg2
psycopg2-binary
.env
docker-compose.ymlで使用されている変数があると思います。($DJANGO_SECRET_KEY)
これは、Djangoのプロジェクト作成時に発行されるキーなのですが、環境変数に設定しようかと思って普通に記述すると、以下のエラーが発生。
(何故環境変数に、DjangoのSECRET_KEYを設定しようと思ったかというと、毎回毎回Docker環境を作成しては削除していると、Githubでのヴァージョン管理の際に、settings.pyは管理したいけど、SECRET_KEYは別で管理したいということになりました。)
ERROR: Invalid interpolation format for "environment" option in service "web": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
どうやらエスケープしなければならない記号が入っていて、environmentに直接値を記述できませんでした。(やり方はあるが面倒くさい..w)
なので、.envというファイルを作成し、これをヴァージョン管理。
え、ヴァージョン管理するの?って思うかもしれませんが、これには理由があります。
1つ目としては、他の人に同じ.envを提供できる。(= 同様な環境構築を目指す。)また、開発環境においては他の値で代用できたりしますね。
2つ目は、STGや本番では、OSの環境変数を見に行くので大丈夫ということ。ただし、これはあくまで、本番サーバーでDockerを稼働させないことになります。
まあ、とりあえずローカル環境はDockerで!みたいな人向けになってしまいますが...(でも会社とかで作業していると、新機能作成で本番はDockerじゃないけど、機能追加のためにDocker流行ってるし今回のローカル環境はDockerにしよう!って人も多いのでは?w)
それはさておき、.envには以下を記述
DJANGO_SECRET_KEY=-<今は適当な値をとりあえずいれておく>
DJANGO_DEBUBG=True
ProjectとAppを作成
コマンドを実行してプロジェクトとアプリを作成します。
プロジェクトルートにて、以下を実行。
# プロジェクトを作成
$ docker-compose run web django-admin.py startproject settings .
# アプリケーションを作成
$ docker-compose run web python manage.py startapp src
これを実行すると、プロジェクト構成は以下のようになるかと思います。
<project_name>
├── Dockerfile
├── README.md
├── db.sqlite3
├── docker-compose.yml
├── manage.py
├── mysql
│ └── init
│ └── <file_name>.sql
├── requirements.txt
├── settings
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── urls.cpython-35.pyc
│ │ └── wsgi.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── src
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
一気にファイルやらディレクトリが作成されたかと思います。
今回、プロジェクトとアプリの作成コマンドの名前をsettingsとsrc
にしました。
これは任意です。ディレクトリ名としてわかりやすいものでいいと思います。
/settings/settings.py
を編集します。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql,
'NAME': <db_name>,
'USER': '<user_name>,
'HOST': 'db',
'PORT': 3306,
}
}
- PyMySqlの読込
同ファイル、任意の箇所に以下を記述
import pymysql
pymysql.install_as_MySQLdb()
また、このファイルにSECRET_KEY
が記述されているかと思います。
この値を.envのDJANGO_SECRET_KEY
に追記し、
settings.pyのSECRET_KEYの部分に、os.environ.get('DJANGO_SECRET_KEY')
を代わりに書いて、OSの環境変数を参照するようにします。
合わせて、DEBUGもos.environ.get('DJANGO_DEBUBG')
として書き換えます。
その他、プロジェクトに合わせて、LANGUAGE_CODEとTIME_ZONE
も合わせます。
(体外が、ja
とAsia/Tokyo
でしょうか。)
INSTALLED_APPS
にもこちらを追記します。'rest_framework'
DBとのシンクのために、マイグレーションファイルを作成します。
models.pyに対象のテーブル(class)を記載して実行すると、src/migrations/
ディレクトリが作成され、
0001_initial.py
のようなファイルが作成されます。
はじめにmodels.pyが空の状態でmigrate
をしても大丈夫ですが、src/migrations/
配下にはini.pyしか作成されません。
# ホストからマイグレーションファイルををDBに適用
$ docker-compose exec web python manage.py makemigrations
# Dockerコンテナの中に入ってマイグレーションファイルをDBに適用
$ python manage.py makemigrations
# ホストからmodels.pyに書いたclassを読み込んでマイグレーションファイルを作成
$ docker-compose exec web python manage.py makemigrations <app_name>
# models.pyに書いたclassを読み込んでマイグレーションファイルを作成
$ python manage.py makemigrations <app_name>
ググってみるとほとんど記事が新規でお試しテーブルみたいなかんじでmodels.pyに記述していますが、
既存のdumpファイルから作成されたDBから以下のコマンドで、models.pyに自動でclassを作成してくれます。
$ python manage.py inspectdb tabbel_name >> models.py
実行
最後に実行です。
$ docker-compose up
.
.
.
<container_name> | You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
<container_name> | Run 'python manage.py migrate' to apply them.
<container_name> | November 19, 2018 - 19:51:55
<container_name> | Django version 2.1.1, using settings 'settings.settings'
<container_name> | Starting development server at http://0.0.0.0:8080/
<container_name> | Quit the server with CONTROL-C.
このような出力されればOKでしょう。
http://localhost:8080/
ブラウザでlocalhostにアクセスし、Welcomeページが表示されていれば、あとはもう開発を開始できます!
まとめ
だいぶ駆け足で書きました。
うまくいかない場合は、もちろん公式を参照してみて下さい。
確認としては、Dockerのコンテナにはいることで解消できる場合もあります。($ docker exec -i -t コンテナ名 bash
)
また、Dockerのコンテナは何度削除しても大丈夫です!($ docker rm <CONTAINER ID or NAMES>
)
1からのやり直しも簡単にできるのはDockerのいいところでもあるのかなと思います。
今回私は、初期データとして、5GBのdumpファイルを用いましたが(ちょっと最初のイメージコンテナ作成時時間はかかりますが、)問題なく動作しています。
後先考えると環境構築はほんとに大変...
ですが、とりあえず構築させていくことが大事ですね!
以上.