Docker ComposeでDjangoの開発環境を構築した

これまで一つのコンテナにMySQLやWordPressをまとめて突っ込んで動かしていたのですが、そのような素人的な使い方を脱出しようと思い、Docker Composeの使い方を学ぶことにしました。

Docker Composeは複数のコンテナをポコポコ立ててくれるツールです。

Dockerはデータベース、サーバー、バックエンド、フロントなど、役割ごとにコンテナを用意してアプリ構築することを推奨していますが、それぞれのコンテナを一つずつ用意していくの面倒ですよね。そこでDocker Compose。これを使うことで一度に複数のコンテナを積み上げて、瞬時に環境を構築することができます。

今回は練習がてら、Djangoの開発環境を作ってみます。

はじめに

DockerとDocker Composeが必要なので、インストールします。

コンポーネントの定義

次のようにDBとWebのコンテナで構成します。

  • Web…Pythonのイメージから起動したDjangoのコンテナ
  • DB…PostgreSQLのコンテナ

必要なファイルとディレクトリは下記の通り。

.
├── Dockerfile
├── docker-compose.yml
└── requirements.txt

Dockerfileの準備

PythonのイメージにDjangoを突っ込むため、Dockerfileを準備します。

FROM python:3.7
ENV PYTHONUNBUFFERED 1
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt

FROM python:3.7

version3.7のPythonが格納されたイメージを指定しています。

ENV PYTHONUNBUFFERED 1

コンソールのstdout(標準出力)とstderr(標準エラー出力)のバッファーを無効にする設定です。

例えば次のようなコマンド。数字の 10 が出力された後、5秒待った後に数字の100が出力される単純なコマンドですが、 cat コマンドをパイプに通しています。

python -c 'import time; print(10); time.sleep(5); print(100)' | cat

バッファーが有効な場合、5秒後のタイミングで数字の10と100が同時に出力され、本来意図したものと異なる出力になります。 PYTHONUNBUFFERED でバッファーを無効にすることで、このような挙動を抑止することができます。

ADD requirements.txt /code/

`WORKDIR /code` `ADD requirements.txt /code/` `RUN pip install -r requirements.txt`

これはDockerfileと同じディレクトリに用意したrequirements.txtをイメージの /code ディレクトリに配置し、必要なツールのインストールを行います。

requirements.txtの準備

PythonのイメージにDjangoとPostgreSQLのライブラリをインストールするために使います。

Django==2.1.1
psycopg2
psycopg2-binary

docker-compose.ymlの準備

Docker Composeの要となるymlファイルです。どのようなコンテナのアプリ構成にするのかをこのファイルで設定します。

version: "3"

services:
  db:
    image: postgres:10
  web:
    build: .
    volumes:
      - .:/code
    tty: true
    ports:
      - 8000:8000
    depends_on:
      - db

version: “3”

ymlのファイル形式を指定しています。

services:

このハッシュの配下にコンテナの情報をまとめていきます。

db:

データベース用のコンテナを設定しています。

web:

Djangoアプリ用のコンテナを設定しています。

build: .docker-compose.yml が置かれているディレクトリのDockerfileを指定してイメージをビルドしてくれます。

volumes:docker-compose.yml が置かれているディレクトリをコンテナの /code へマウントします。

tty: true、コンテナを起動したままにするオプション。シェルを実行するようなコンテナを使う場合に必要。

ports:、ホストの8000番からコンテナの8000番へポートフォワード。

depends_on: これを指定すると、指定したコンテナの起動を待ってから対象のコンテナを起動します。

サービスの起動

docker-compose.ymlが置かれているディレクトリへ移動し、次のコマンドを実行します。

docker-compose up -d

-dオプションでデタッチモードでコンテナ群を起動させます。アクセスログの内容やエラーなどを確認したい場合は、-dを外して実行します。

実行するといい感じにコンテナが二つ動いているはず。

docker container ls
# docker container lsコマンドの出力結果の例
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                    NAMES
1a4665029e96        django-dev_web       "python3"                9 seconds ago       Up 7 seconds        0.0.0.0:8000->8000/tcp   django-dev_web_1
350f65de1ef2        postgres:10          "docker-entrypoint.s…"   10 seconds ago      Up 9 seconds        5432/tcp                 django-dev_db_1

Djangoプロジェクトの作成

起動したWebコンテナで django-admin startproject コマンドを実行します。

docker container exec -it {CONTAINER_NAME} django-admin startproject {PROJECT_NAME}

例: docker container exec -it django-dev_web_1 django-admin startproject test

成功すると、指定したプロジェクトが作成されます。

.
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── test # <--PROJECT_NAME
    ├── manage.py
    └── test
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

Djangoプロジェクトの環境変数の設定

作成されたプロジェクト配下にある settings.py を開き、 DATABASES 関数を書き換えます。必要に応じて ALLOWED_HOSTS の値も修正します。

DATABASESの設定

DATABASESを次のように書き換えて、PostgreSQLのコンテナと通信できるようにします。

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.postgresql',
    'NAME': 'postgres',
    'USER': 'postgres',
    'HOST': 'db',
    'PORT': 5432,
  }
}

ここで大事なのが、 HOST で指定している db という値。これはdocker-compose.ymlで設定したPostgreSQLのサービス名と同じにする必要があります。通常、 HOST にはホスト名だったりIPアドレスを入れるのですが、docker-compose.ymlの設定にしたがって、いい感じに名前解決してくれます。

ALLOWED_HOSTSの設定

これは環境によるのですが、Dockerを動かしているホストの名前、IPアドレスを入力します。例えば↓このような感じです。

ALLOWED_HOSTS = ['localhost', '192.168.33.15', '[::1]']

開発環境と割り切って使うのであれば、次のように全て許可してもいいでしょう。

ALLOWED_HOSTS = ['*']

Djangoプロジェクトの起動

これで準備が整いました。Djangoのサーバーを起動し、ブラウザからアクセスします。

docker container exec -it {CONTAINER_NAME} python {PROJECT_NAME}/manage.py runserver 0.0.0.0:8000

例: docker container exec -it django-dev_web_1 python test/manage.py runserver 0.0.0.0:8000

ブラウザへのアクセス例: http://192.168.33.15:8000

Djangoアプリのようこそ画面

まとめ

Docker Composeを使ってDjangoの開発環境を作りました。これでDjangoをいじり放題です。やったね!