TL;DR
今回はdocker composeのdjangoクイックスタートをやりつつdjangoと戯れる
[結論]
docker-composeだとdocker-compose run container django-admin.py startproject
でローカルにプロジェクトディレクトリを展開して、volumes: .:WORKDIR/
でdockerコンテナにマウントしてプロジェクトを起動する。
前提
- docker導入済み
- docker-compose導入済み
ディレクトリ構造(自分で用意する構成)
WORKDIR
∟Dockerfile
∟requirements.txt
∟docker-compose.yaml
構築
①Dockerfileを書く
Dockerfile
FROM python:3.7
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip3 install -r requirements.txt
ADD . /code/
よくわかる解説
FROM python:3.7
pythonのコンテナイメージをDocker hubから引っ張ってくる
元のpythonのversionは2.7になってたので、3.7に直す
ENV PYTHONUNBUFFERED 1
標準出力STDOUT,STDERRのバッファを無効化するものらしい
なんかバッファ有効にしてるとsleep()とかの挙動がおかしくなるとかならんとか
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
codeというフォルダを作ってワーキングディレクトリに指定してそこに後述するrequirements.txtを置く(ホスト側のファイルを指定の場所に置く)
RUN pip3 install -r requirements.txt
後述するrequirements.txtに書いたものをpipでインストールする。
python3系への変更に伴いpipも3を使う
ADD . /code/
カレントディレクトリ以下をコンテナ上のフォルダに置く
requirements.txt
Django>=2.0,<3.0
psycopg2>=2.7,<3.0
よくわかる解説
Django>=2.0,<3.0
今回の主旨
bottleやflaskと同じく、pythonのwebフレームワーク
どっかで見たのは、
django > flask > bottle
大規模向け ⇔ 小規模向け
らしい。眉唾。
元のテキストにはバージョン指定が無かったので追加
psycopg2>=2.7,<3.0
PythonのPostgreSQLドライバらしい
今回はDBとしてpostgresのコンテナを上げるのでインストール
元のテキストにはバージョン指定が無かったので追加
②docker-compose.yamlを書く
docker-compose.yaml
version: '3'
services:
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
よくわかる解説
version: '3'
docker-composeのファイルフォーマットのバージョン。
最新が3らしいし最近3をよく見る(2ってオワコンなんですか?)が深入りしないと決めている。違いについては各自調べて優しく教えてください。
services:
db:
image: postgres
一つめのDockerコンテナ。
image句は、Dockerレポジトリから指定のコンテナイメージを引っ張ってきて起動する。
今回はPostgreSQL。しかしこのチュートリアルは意地でもバージョン指定しないな。。
バージョンを指定したいときは後ろにタグをつけてあげる。「postgres:11.2」とか。
web:
build: .
二つめのDockerコンテナ。
image句がない場合、build句で指定したディレクトリにあるDockerfileをビルドして起動する。
command: python manage.py runserver 0.0.0.0:8000
コンテナの起動時に実行されるコマンド。いわゆるDockerfileで言うところのCMD句。
CMD句がdocker run -it [container] [command]
のcommandに上書きされてしまうように、docker-compose run でコマンドを指定した場合、ここに書いた命令は上書きされる。
コマンドは、djangoのwebアプリケーションを起動させるコマンド。localhost向けの8000番で待ち受ける。
volumes:
- .:/code
ホストディレクトリをコンテナ上の/codeディレクトリにマウントする。
ググってもググってもこのパターンしか出ないが、こういうのってk8sで実際に構築するときはどうするんでしょうね。DockerfileにCOPYとか書くからいいんですかね。
ports:
- "8000:8000"
ホストの8000ポートをコンテナの8000ポートにフォワーディングする。
depends_on:
- db
dbコンテナが起動してから、このコンテナを起動する。DBが絡む時とかは起動順を気にしてあげなくてはいけない。
③docker-compose runの実行
$ docker-compose run web django-admin.py startproject composeexample .
docker-compose runは、デフォルトでdocker runの-itオプションがつくらしい。
つまり、webコンテナを立ち上げてdjango-admin.py startproject composeexample .
を実行しているということ。
django-admin startproject [project名] [展開先のディレクトリパス]は、djangoでプロジェクトを作るときのコマンドらしく、テンプレートが指定したディレクトリパス上に展開される。
ここでは先ほど、/codeにホストディレクトリをマウント指定したので、ホストディレクトリ上に展開される。
上記実行後のディレクトリ構成は下記のような感じになるはず。
WORKDIR
∟composeexample
∟__init__.py
∟settings.py
∟urls.py
∟wsgi.py
∟Dockerfile
∟requirements.txt
∟manage.py
∟docker-compose.yaml
ちなみにlinuxマシンで実行した場合はフォルダの権限がrootになるらしいので、下記を実行する。
sudo chown -R $USER:$USER .
postgreSQLと接続するために、settings.pyのDATABASES =
部分を書き換える。
④setting.pyの編集
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
⑤docker-compose upによる実行 …と紆余曲折
docker-compose up
いざ実行。
…動かんじゃないか。ググると同じエラーに遭遇した人が。
なんかDB名とかUSER名とかをdb側の環境変数で指定しないといけないみたい。
あとついでにポート指定しなくてもエラーが出た。
version: '3'
services:
db:
image: postgres
ports:
- "5432"
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
docker-compose up
今度こそ。
web_1 | Watching for file changes with StatReloader
web_1 | Performing system checks...
web_1 |
web_1 | System check identified no issues (0 silenced).
web_1 |
web_1 | You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
web_1 | Run 'python manage.py migrate' to apply them.
web_1 | April 22, 2020 - 08:14:48
web_1 | Django version 2.2.12, using settings 'composeexample.settings'
web_1 | Starting development server at http://0.0.0.0:8000/
web_1 | Quit the server with CONTROL-C.
通った。実はこの作業EC2上でやっていたので、http://server_ip:8000
にアクセスしてみる。
ほう。。
バージョン1.10以降のdjangoではアクセス許可をsetting.pyに書いてやらねばならぬらしい。
ALLOWED_HOSTS = ["*"]
※本番環境でアスタリスクはやらないように。
docker-compose up
三度目の正直。