今回は、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つのファイルの記述です。
- Dockerfile
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/
- docker-compose.yml
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
にしました。
これは任意です。ディレクトリ名としてわかりやすいものでいいと思います。
mysqlとの接続
/settings/settings.py
を編集します。
- DBの設定
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でしょう。
ブラウザでlocalhostにアクセスし、Welcomeページが表示されていれば、あとはもう開発を開始できます!
まとめ
だいぶ駆け足で書きました。 うまくいかない場合は、もちろん公式を参照してみて下さい。
確認としては、Dockerのコンテナにはいることで解消できる場合もあります。($ docker exec -i -t コンテナ名 bash
)
また、Dockerのコンテナは何度削除しても大丈夫です!($ docker rm <CONTAINER ID or NAMES>
)
1からのやり直しも簡単にできるのはDockerのいいところでもあるのかなと思います。 今回私は、初期データとして、5GBのdumpファイルを用いましたが(ちょっと最初のイメージコンテナ作成時時間はかかりますが、)問題なく動作しています。
後先考えると環境構築はほんとに大変... ですが、とりあえず構築させていくことが大事ですね!
以上.