【Docker初心者向け】Dockerを使用してDjangoの開発環境を構築する

この記事は、2023年5月に作成した記事です。

# はじめに
Djangoの環境をDockerで構築する際に、少しつまづいたので、記事にまとめて考えを整理したいと思いました。<br>
**書いた人**

Dockerについては全くの初心者で業務経験もありません。
Django・Pythonについても多少の知識はありますが、初心者の域を出ていません。

**環境**
- macOS Monterey == 12.5
- Docker == 23.0.5

**前提**
- Djangoについては多少触れたことがある
- Dockerをインストール済みである
- VSCodeでDockerの作業できる

**今回のソースコード**

https://github.com/a-im12/Django_introduction_with_Docker

# この記事でできること
この記事では、Djangoのスタートページを表示するところまで手順を記述します。![django.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3411675/a26e28bc-dd87-087b-76df-a88a4aaa73c4.png)

# Dockerfileの記述
まずは任意のディレクトリにフォルダを作成します。ここでは「containers」というフォルダ名にします。
~~~
├── README.md
└── containers      # 新たに作成
    └── Dockerfile  # 新たに作成
~~~
READMEは無視してください。
~~~Dockerfile
FROM python:3.9.11

ENV PYTHONUNBUFFERED 1

RUN mkdir -p /root/workspace
COPY requirements.txt /root/workspace/
WORKDIR /root/workspace

RUN pip install --upgrade pip\
    && pip install --upgrade setuptools\
    && pip install -r requirements.txt
~~~
**要点の説明**
- **FROM : python:3.9.11**
使用するPythonのDockerイメージを指定します。今回は、バージョン3.9.11のPythonを使用しています。

- **ENV PYTHONUNBUFFERED 1**
標準出力と標準エラー出力をバッファリングしないようにするための環境変数の設定です。
私も詳しくはわかっていないのですが、デバッグがしやすくなるように記述するようです。

- **RUN mkdir -p /root/workspace**
作成する仮想環境のルートディレクトリに任意のディレクトリを作成します。
-pのオプションにより、指定した親ディレクトリが存在しない場合は、親ディレクトリを含めて、自動的に生成してくれます。

- **COPY requirements.txt /root/workspace**
requirements.txtファイルを任意のディレクトリにコピーしています。
requirements.txtファイルはこの後作成していきます。

- **WORKDIR /root/workspace**
仮想環境を実行した時にアクセスするディレクトリをしています。
基本、Dockerコンテナを起動すると、その元となっているDockerイメージが指定したディレクトリにアクセスします。
しかしそれだと、チームで開発する際に、作業ディレクトリを統一しにくいため、みんなで作業場所を統一するために指定しています。

- RUN pip ~~
ここでは、pipによるライブラリのインストールを行なっています。
ここで出てきた「\」は、改行を表します。Dockerfile内で改行して続きを記述したい場合は、文末にバックスラッシュを記述しましょう。
また、このpipの部分は

~~~
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install -r requirements.txt
~~~
と書き換えることもできます。
あえてRUN一つにまとめている理由は、dockerイメージの容量を少なくするためです。

# requirements.txtの作成
次にrequirements.txtを作成していきます。
このファイルの役割としては、使用したいライブラリを記述しておくことで、Dockerfileがこれを参照し、インストールしてくれます。
これにより、**pip install**を大量に実行する必要がなくなり、楽になります。
このファイルを作成する場所は、DockerFileと同じcontainersフォルダの中になります。
~~~
├── README.md
└── containers
    ├── Dockerfile
    └── requirements.txt　　　# 新たに作成
~~~
今回はバージョン4.1のDjangoをインストールします。
また、Djangoのみのインストールなので、記述する内容は1行で終わりです。
~~~requirements.txt
django == 4.1
~~~
# composeファイルの記述
composeファイルを作成していきます。
composeファイルはcontainersフォルダと同じ階層に作成していきます。
~~~
├── README.md
├── containers
│   └── Dockerfile
└── docker-compose.yml　　　# 新たに作成
~~~
~~~docker-compose.yml
version: '3'

services:
  # サービス名
  django:
    build:
      context: ./containers    # Dockerfileがあるディレクトリまでの相対パス
      dockerfile: Dockerfile   # Dockerfileのファイル名
    
    # 作成するコンテナ名の指定
    container_name: django

    # 使用するポートの設定
    ports:
      - "8000:8000"
    
    # 対話的なセッションやコマンドラインの操作を許可する
    tty: true

    volumes:
      # ローカルの作業ディレクトリと仮想環境の作業ディレクトリの対応づけ
      - ${SRC_PATH}:/root/workspace   
~~~
composeファイルの記述はこれで終わりです。
ただ、composeファイルのvolumesで使用されている環境変数の**SRC_PATH**を定義しなければなりません。

# .envファイルの記述
composeファイルで使用している環境変数を定義するためのファイルです。
composeファイルと同じ階層に.envファイルを作成します。
~~~
├── README.md
├── containers
│   ├── Dockerfile
│   └── requirements.txt
├── .env #新たに作成
└── docker-compose.yml
~~~
~~~.env
SRC_PATH = ./src
~~~
今回使用する環境変数は、1つだけなので、記述する内容は以上になります。
# composeファイルのビルド・実行
ここまでで、必要なファイルの記述はすべて終わりました。
次は、実際にcomposeファイルをビルドして、実行してみましょう。
まずは、ターミナル上で、composeファイルがあるディレクトリまで移動します。
~~~
cd #composeファイルの存在するディレクトリ
~~~
次にcomposeファイルをビルドします。
~~~
docker-compose build
~~~
すると、composeファイルやDockerファイルが実行され、必要なdockerイメージのpullやrequirements.txtに記述したライブラリのインストールが始まります。
何もエラーがなければ、再度自分のホスト名が表示されます。

次に、ビルドしたコンテナの実行です。
下記のコマンドを実行するとコンテナが実行されます。
~~~
docker-compose up
~~~
コンテナの実行が成功すると、composeファイルと同じディレクトリに、「src」というフォルダが自動で生成されます。
~~~
├── README.md
├── containers
│   ├── Dockerfile
│   └── requirements.txt
├── docker-compose.yml
└── src   # 新たに生成
~~~
この生成されたフォルダ内が、作業ディレクトリとなります。
これで無事、Dockerを使用してDjangoの環境を構築できました!!

# 発生したエラーの内容と原因
私の場合はrequirements.txtがうまく参照できずに、エラーが出てしまいました。
~~~
 => ERROR [5/5] RUN pip install --upgrade pip && ...
~~~
エラーの後には解決方法として、以下のものが紹介されていました。
~~~
failed to solve: process "/bin/sh -c pip install --upgrade pip && ...
~~~
「Dockerfileの該当する行を次のように変更すれば解決できるかもよ」といった内容です。
言われた通りに変更すると、うまくエラーは消えたのですが、ライブラリはインストールされていませんでした。

このエラーの原因としては、requirements.txtをうまく参照できていないことによるものなので、Dockerfileの内容をよく見直したところ...

COPYの行で末尾の「/」が抜けていました。
~~~Dockerfile
COPY requirements.txt /root/workspace/　　#ここの末尾の「/」が抜けていた...
~~~
「/」がないと、ディレクトリを指定するのではなく、ファイル名を指定してコピーしてしまいます。
このせいでうまくビルドできませんでした。

# Djangoプロジェクトの作成
次に、VScodeで実行しているコンテナへアクセスします。
VScodeに導入した拡張機能は以下の2つです。
[Docker - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)
[Dev Containers - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)

コンテナへアクセスして、ターミナルを表示できたら、Djangoプロジェクトを作成するコマンドを実行します。
ここでは、作成するプロジェクト名を「sample」としています。
~~~
django-admin startproject sample
~~~
コマンドを実行すると、srcフォルダのなかに、新たにプロジェクトフォルダが生成されます。
~~~
├── README.md
├── containers
│   ├── Dockerfile
│   └── requirements.txt
├── docker-compose.yml
└── src
    └── sample   #プロジェクトフォルダが生成される
        ├── manage.py
        └── sample
            ├── __init__.py
            ├── asgi.py
            ├── settings.py
            ├── urls.py
            └── wsgi.py
~~~
# サーバーの起動
プロジェクトの作成も完了したので、ついにサーバーを起動してロケットページを見てみましょう。

まずはsetting.pyを編集します。
~~~setting.py
ALLOWED_HOSTS = ['*']
~~~
setting.pyにある**ALLOWD_HOSTS**という環境変数に「'*'」を追加します。
このように設定することで、すべてのアクセスを許可する仕組みになっています。もし公開する際は、その時に適切に編集し直してください。

これで準備完了です！
早速サーバーを立ち上げてみましょう！
~~~
python manage.py runserver 0.0.0.0:8000
~~~
ここで1つ注意があります。
runserverの後には、アドレスとポートを指定してあげましょう。
runserverのみで実行した場合、ローカルからサーバーにアクセスできません。

# サーバーへのアクセス
サーバーが無事起動できたら、実際にアクセスしてみましょう。
![django.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3411675/2b15e5d0-4690-6f99-367f-b15a24cbde76.png)
無事アクセスできました！

今回はこれで終了です！
構築した環境でさまざまなアプリを開発してみてください！

# 終わりに
記事にまとめることで、自分の中で理解がより深まった感じがします。
私は、構築した環境でチャットアプリを作成していきたいと思います。

読んでいただき、ありがとうございました。