docker-compose×Django×Postgresqlの開発環境構築

# 目的
公式リファレンスを参考にしてdocker-compose×Django×Postgresqlの開発環境構築をする。

# 環境
MacBook Pro(intel)
Docker Desktop
Django3.2
python3.8.5
postgres12

# 前提
1. docker,docker-composeがインストールされている状況
2. [公式リファレンスを参考にしています](https://docs.docker.jp/compose/django.html)
2. 利用するバージョンは公式とは違いますが、2021年10月時点で動作が確認出来ているものです。


# スタート
## プロジェクト用の空のディレクトリを作成
`% mkdir docker-compose-test`
`% cd docker-compose-test`


## 作成したプロジェクトディレクトリ内にDockerfileを作成する。

`% vi Dockerfile`

```dockerfile
FROM python:3.8.5 
ENV PYTHONBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
``` 
#### Dockerfileの中身
`FROM`: ベースとなるイメージを指定します。

`ENV`：永続的な環境変数を設定します。 
今回は`PYTHONBUFFERED 1`としました。これは標準エラー出力を[バッファ](https://www.otsuka-shokai.co.jp/words/buffer.html)に溜め込まない指示をしています。

`RUN`：イメージ作成時に実行。イメージ作成後に`/code`というディレクトリを作成しています。

`WORKDIR`：各種命令を実行する際のカレントディレクトリを指定します。 RUNで作成したcodeディレクトリがWORKDIRとなります。

`ADD`:ローカルファイルやディレクトリをコピーし、コンテナ内のファイルシステム上にある指定されたパスに追加します。ここでは作成したcodeディレクトリにコピーします。また、URLを指定することも出来ます。この場合はリモートイメージをcodeディレクトリにダウンロードしてADDすることが出来ます。※requirements.txtは後ほど作成します。

`RUN`:FROMで指定したイメージ上で、シェル形式のコマンドを実行します。ここでは、後ほど作成するrequirements.txtに記載したシステムをpipでインストールしています。

`ADD`:カレントディレクトリ`.`を codeディレクトリにコピーしています。

以上

作成したら保存して閉じます。

## requirements.txtの作成
Dockerfileと同じディレクトリにrequiremenrs.txtを作成します。
`% vi requirements.txt`

```requirements.txt
Django=3.2
psycopg2
```

#### requirements.txtの中身
Dockerfileで支持したrequirements.txtをここで作成しています。
`Django=3.2`:インストールするDjangoのバージョンを指定。

`psycong2`:postgresqlのドライバーを指定しています。

作成したら閉じます。

## docker-compose.ymlの作成
`% vi docker-compose.yml`

```docker-compose.yml
version: '3'

services:
  db:
    image: postgres
    ports:
      - "5432"
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
  web:
    build: .
    command: python3 manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

```

#### docker-compose.ymlの中身

`version`:docker-composeのバージョンを指定。

`services`:ここに作成するコンテナをを定義していきます。ここではdbとwebコンテナを作成しています。

`db`：使用するデータベースを指定します。ここではimageをpostgresを指定してます。
`ports`:DBコンテナとwebコンテナの接続ポートを指定しています。5432はpostgresｑｌのデフォルトのポート番号です。
`enviroment`:環境変数を定義しています。これもpostgresqlの設定になります。

`web`:webサーバーを指定しています。ここではDjangoに備わっている開発webサーバーの使用を前提としています。
`build`: Dockerfile のあるディレクトリのパスを指定します。この値が相対パスで指定された場合は、yml ファイル自身がある場所からの相対パスになります。また、ディレクトリは内容構築のため、Docker デーモンにも送られます。


`command`:`docker-compose up`でファイルを実行する時に実行するデフォルトのコマンドを指定しています。Dockerfileでも`CMD`でコマンドを指定できますが、こちらは`docker run`コマンド時（イメージをビルドする時）に実行する時に指定します。

`volumes`:パスをボリュームとしてマウントします。オプションとしてホスト側のパスを指定（ホスト:コンテナ）したり、アクセスモードを指定します（ホスト:コンテナ:ro）。ここではホスト側のカレントディレクトリとりもーと側のcodeディレクトリをvolumeとして共有することになります。

`ports`: ポートを公開（expose）します。ホストとポートを指定（ホスト:コンテナ）するか、コンテナのポートのみ指定します（ホスト側のポートはランダムに選ばれます）。

`depends_on`:コンテナの依存関係を指定します。ここではdbコンテナと依存関係を持っていることがわかります。

## Djangoプロジェクトの作成

プロジェクトディレクトリに移動し、`docker-compose run`コマンドを実行しdocker-compose.ymlで定義したビルドコンテキストを実行しコンテナを作成します。

1. `% cd <プロジェクトディレクトリ>`
1. `% docker-compose run web django-admin.py startproject composeexample .`
    1. web サービスイメージがビルドされると Compose はこのイメージを起動し、コンテナ内でコマンド django-admin startproject を実行します。 このコマンドは Django に対して、Django プロジェクトを組み立てるファイルやディレクトリを生成することを指示するものです。
1. コンテナが作成されているか確認
    1. `% docker ps -a`

## Postgresqlの設定
Djangoプロジェクトが作成されたら、setting.pyを開いてDatabase設定を編集する。

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

ここでの設定は[postgresqlの設定](https://hub.docker.com/_/postgres?ref=login)に準じて行います。

## コンテナを起動
プロジェクトディレクトリに移動し、
`% docker-compose up`コマンドを実行してコンテナを起動する。

ブラウザーで`127.0.0.1:8000`にアクセスしてdjangoのデフォルトページが表示されれば成功です。＼(^o^)／

ありがとうございました。


## 参考にさせていただいたページ
* [djangoとpostgresqlをDockerで接続しようとしたときに「django.db.utils.OperationalError: could not translate host name "db" to address: Name or service not known」というエラーが出る](https://qiita.com/takos/items/c04ac2a64d519894ee13)
* [Docker一括削除コマンドまとめ](https://qiita.com/boiyama/items/9972601ffc240553e1f3)
* [Dockerfile リファレンス](https://docs.docker.jp/engine/reference/builder.html)
* [コマンドはdocker-compose.ymlとDockerfileのどちらで定義するほうがいい？](https://ja.stackoverflow.com/questions/30495/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AFdocker-compose-yml%E3%81%A8dockerfile%E3%81%AE%E3%81%A9%E3%81%A1%E3%82%89%E3%81%A7%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%81%BB%E3%81%86%E3%81%8C%E3%81%84%E3%81%84)
* [クィックスタート: Compose と Django](https://docs.docker.jp/compose/django.html)