Djangoの開発環境を作ってみる

# Djangoの開発環境を作った際の覚え書
Djangoの勉強１日目に学んだことを記しておきます。
情報系大学生の初心者です。
不適切な点がありましたらコメントいただけると幸いです。
## Djangoとは？
Pythonのフレームワークの１つ。拡張性が高く、大規模なWEBアプリの開発に向いている（らしい）。

## なんでDjangoを始めようと思った？
同じくPythonフレームワークのFlaskで研究用のアプリを作っているが、Flaskは小規模向け...。もっといろんな機能を搭載したアプリを作ってみたいという憧れから始めてみました。

## ここで作るもの
未定。だが、大規模なもの。

バックエンド：Django
DB管理システム：PostgreSQL

今回は大規模開発を行うため、複雑なDB操作にも対応できるPostgreSQLをDB管理システムとして採用します。

## 開発環境を構築しよう
自分のPCをあんまり汚したくない（モジュールであふれかえりたくない）ので、仮想環境で開発を進めます。仮想環境の構築にはいろんな手法があるが、（これも憧れで）Dockerで仮想のコンテナを立てて開発を行います。

### そもそも仮想環境って何？

マンションに例えて考えてみましょう。

だだっ広い空間ですべての住人が生活するとしましょう。それぞれの住人が生活するには、共同スペースに全住人が使う用の家具を置く必要があります。
曲を聴くことが好きな住人のためのスピーカー、料理が好きな住人のための広いキッチン...etc。
これではオーナーは破産してしまいますし、曲を聴くのが嫌いな住人にとってはスピーカーは邪魔なモノになってしまいます。

そこでオーナーは考えました。
部屋を作ろう！
各住人に部屋を与えて、家具はその住人専用のものにします。
これで、曲を聴くのが好きな人と嫌いな人が共存できるようになりました。

環境の話に戻ります。

ローカル環境とは前者（だだっ広い空間の方）、仮想環境とは後者（部屋の方）です。
ローカル環境で開発に必要なモジュールをインストールしてしまうと相性によって衝突が発生することもあります。
仮想環境で、そのモジュールをそのアプリ専用のものにしてしまえば、先ほどのような衝突が発生する可能性は低くなります。

### なぜDockerなのか。

今回作成するアプリは友人とチームを組んで開発を行うため、お互い同じ環境で行いたいと考えました。また、環境構築は慣れていないため一人が頑張って作った環境を共有した方が効率的だと考えました。
Dockerは、Dockerfileを共有して開発者自身の環境で実行すれば同じ環境を構築できるもので、
「Dockerfileを作ってしまえばこっちのもの！」
だと考えました。（安直）

### 作業環境
Windows11
### 準備（ここでは説明を省きます）
- dockerとdocker-desktopのインストール
- VScodeのインストール

## Dockerfileを作成する

まずDockerfileを作成し、以下のコードを記述します。
```Dockerfile
FROM python:3.11
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
```
ファイルの内容を解説すると、
- この環境では、python3.11でコードを記述します
- 環境変数「PYTHONUNBUFFERED」は、1にします
- codeディレクトリを作成します
- 上で作ったcodeディレクトリを作業ディレクトリとします
- requirements.txtファイルを、codeディレクトリ下に追加します
- requirements.txtファイルに書かれているパッケージをインストールします
- 今いるディレクトリにあるものすべてをcodeディレクトリ下に追加します

## requirements.txtを作成する
requirements.txtとはDjangoアプリに限らず、パッケージのバージョンを書いておくテキストファイルです。
Dockerfileのコードで**pip install -r requirements.txt**とありましたが、このコマンドではrequirements.txtを読み込んで一気にインストールをすることができます。
requirements.txtを作成して以下のように記述します。
```requirements.txt
Django == 4.2.2
psycopg2-binary
```

## docker-compose.ymlを作成する
次にdocker-compose.ymlを作成します。
### そもそもdocker-composeとは
Dockerではコンテナをサービス１つ１つに対して立ち上げます。
例：PostgreSQLコンテナとDjangoコンテナとReactコンテナ

１つのWEBアプリで複数のサービスを使用したい時、使用するコンテナをまとめるものが必要です。それが**docker-compose**です。
### WEBアプリの仕組み
通常、コードはWEBサーバに置かれ、その中で実行されます。
Djangoには試験用のWEBサーバを準備する機能があるとのことなのでWEBサーバもコンテナとして立ち上げます。

### docker-compose.ymlを書く
docker-compose.ymlを作成し、以下のコードを記述します。
```docker-compose.yml
version: '3'

services:
  db:
    image: postgres
    environment:
      POSTGRES_DB: "[任意のDB名]"
      POSTGRES_USER: "[任意のユーザ名]"
      POSTGRES_PASSWORD: "[任意のパスワード]"
    volumes:
      - postgres_data:/var/lib/postgresql/data
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: python3 manage.py runserver 0.0.0.0:8000
    volumes:
      - ./django_app:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

volumes:
  postgres_data:
```
このdocker-composeではDBとバックエンドを管理するため、DBのサービスを**db**、Webサーバのサービスを**web**と命名しておきます。これはコンソールなどでログとして表示されるときに使われる名前なので、分かりやすい名前にしておきましょう。

:::note alert
WEB上に公開する際は、environmentの部分は.envファイルから読み込むように設定しましょう
:::


#### PostgreSQL
PostgreSQLは、既にDocker Hubで公開されているイメージをビルドしてコンテナを構築します。
environmentプロパティにて、環境変数各種を設定します。こちらは任意のものを自分で設定します。
volumesを設定しておきます。ここを設定しておかないと`docker-compose up`を実行するたびにデータが消えます...。（私はここで詰まりました)
</dl>

#### WEBサーバ
Djangoの開発用WEBサーバは、先ほど作成したDockerfileの内容をもとにコンテナを構築します。
docker-compose.ymlの実行時に、ビルド時に作成されたmanage.pyを実行、0.0.0.0:8000でサーバを立ち上げます。
volumesプロパティで、ローカルをdocker-compose.ymlのあるディレクトリ、仮想環境内を/codeディレクトリと設定します。
portsプロパティでは、localhostのポート番号8000でリクエストを受信すると、それを仮想環境内のポート番号8000にポートフォワーディングすると設定します。
</dl>

## Dockerfileをビルドする
そもそも、なぜDockerfileを書いていたのでしょうか？
それは開発環境の仕様を決定するためです。

Dockerfileはあくまでテキストファイルであり、その内容を実行しなければただの文字列です。
そこで、**イメージのビルド**という処理を行います。
Dockerfileに書かれたものをDockerイメージと呼び、イメージを基に環境を構築することをビルドといいます。
具体的には以下のコマンドを実行します。
```bash
docker-compose build
```
上のコマンドでは、docker-compose.ymlのあるディレクトリのDockerfileの中身を実行してイメージをビルドしています。

## WEBサーバのプロジェクトを作成する
WEBサーバのプロジェクトを仮想環境内で作成するために、以下のコマンドを実行します。
```bash
docker-compose run django-admin startproject django_app
```
``django_app``を他の任意の名前にしてください
※docker-compose.ymlで指定した'web'ではなく、新しく設定することができます。
## 仮想環境を構築する
いよいよ仮想環境を構築します。
以下のコマンドで実行します。
```
docker-compose up
```
docker-compose.ymlの内容がすべて実行されます。
上のコマンドを実行して[localhost/8000]()にアクセスするとDjangoのページ（正しくはWEBサーバの画面？）が表示されます。
![スクリーンショット 2024-06-30 120829.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827013/6ab9e117-f68e-ae05-c441-7c493ed09731.png)

:::note info
場合により、
```
docker-compose python manage.py migrate
```
の実行を求められることがあります。
DBを更新する必要がありますが、今回は特に関係ありません。
:::
## Djangoアプリを作成する
いよいよ、アプリを作成する段階まで来ました。（お疲れ様です）
試しにhelloアプリを作成してみましょう
```bash
docker-compose run web manage.py startapp hello
```
これでhelloアプリを作成することができました。
helloディレクトリにあるファイルを編集しながらアプリの完成を目指します。

## 最終的なディレクトリ構成
```
project（任意のプロジェクト名）
    - django_app
        - django_app
        - hello/
    - docker-compose.yml
    - Dockerfile
    - manage.py
    - requirements.txt
```

# おわりに 
本記事ではDjangoの学習１日目で行った環境構築についてまとめました。以降、具体的に何を作るのか決まりましたら随時まとめたいと思います。
本記事が誰かの役に立てていれば幸いです。
# 参考にしたサイト
https://qiita.com/kazunobu2211/items/ed12f551be974ce509b4