LoginSignup
3
7

More than 3 years have passed since last update.

素人基盤エンジニアがDockerでDjangoを触るシリーズ①:DockerでDjangoを作る

Last updated at Posted at 2020-04-23

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

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

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

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の編集

settings.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側の環境変数で指定しないといけないみたい。
あとついでにポート指定しなくてもエラーが出た。

docker-compose.yaml
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にアクセスしてみる。
django_error.png

ほう。。
バージョン1.10以降のdjangoではアクセス許可をsetting.pyに書いてやらねばならぬらしい。

setting.py
ALLOWED_HOSTS = ["*"]

※本番環境でアスタリスクはやらないように。

docker-compose up

三度目の正直。

django_success.png
ああ。。やっとロケットが打ちあがった。
俺たちの戦いはまだまだこれからだ!

つづく

3
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
7