Next.js×DjangoアプリケーションをDocker環境で開発する（前編）

## はじめに
基本的に以下の記事をそのまま記載しています。詳細な説明もこちらの方が詳しいです。

https://qiita.com/sinnlosses/items/1e60f89dc3b347a2f3c0


コピペで環境を作成するための個人用備忘録的な位置づけです。

本記事はフロントエンド・バックエンドのアプリケーションを立ち上げるところまでを記載しています。
CRUDアプリケーションの作成は次の記事で記載します。

https://qiita.com/ten-056/items/596984d532363c8dd4c8

## ゴール
以下の構成の3階層Webアプリケーション（簡単なCRUD操作による記事投稿アプリ）をDockerを用いて構築する。
アプリとしての質や各言語への深堀りはスコープ外とする。
- フロントエンド：**Next.JS**
    - TypeScript
    - pagesルーティング（個人的な都合）
- バックエンド：**Django**
    - django REST frameworkによるAPIの実装
- データベース：**PostgresSQL**
    - 特に深い理由はない

## 事前準備
### Docker Desktopのインストール
何かしら調べてインストールする。Macの場合は以下のリンクからインストール可能。

https://docs.docker.com/desktop/install/mac-install/

### プロジェクト用ディレクトリを作成
Dockerでフロント/バックエンドのプロジェクトを作成するが、マウント用のディレクトリを事前に準備しておく。
1. プロジェクトディレクトリの作成
```bash
mkdir sample_project
```
2. マウント先ディレクトリの作成（バックエンド）
```bash
cd sample_project
mkdir backend
```
3. マウント先ディレクトリの作成（フロントエンド）
```bash
mkdir frontend
```
## コンテナの作成
### バックエンド
- Dockerfileの作成
`/backend/Dockerfile`を作成し、以下内容を記載する。
```Dockerfile:/backend/Dockerfile
FROM python:3.10.7
ENV PYTHONONUNBUFFERED 1
RUN mkdir /backend
WORKDIR /backend
ADD requirements.txt /backend/
RUN pip install -r requirements.txt
```

pythonのバージョンは適当な値を設定している。
また、後で用意する`/backend/requirements.txt`をコンテナにコピーしている。
    
- インストールするライブラリの指定 （requirements.txt）
`/backend/requirements.txt`を作成し、以下内容を記載する。

```txt:requirements.txt
Django
psycopg2
djangorestframework
```

順に、Django、PostgreSQLを使うためのライブラリ、DjangoでRestAPIを作成するためのライブラリ。

### フロントエンド
- Dockerfileの作成
`/frontend/Dockerfile`を作成し、以下内容を記載する。
```Dockerfile:/frontend/Dockerfile
FROM node:20.12.1
RUN mkdir /frontend
WORKDIR /frontend
RUN npm install -g npm@latest && npm install create-next-app
```

nodeのバージョンは適当な値を設定している。
また、`npm`とNext.jsプロジェクトをインストールするためのライブラリ`create-next-app`をインストールしている。
 
### docker-compose.ymlを作成
`/docker-compose.yml`を作成し、以下内容を記載する。
PostgreSQLの管理者用GUIに用いる`pgadmin4`について、emailとパスワードは任意のものを入力する。

```yml:docker-compose.yml
version: '3'
services:
  frontend:
    build:
      context: frontend
    tty: true
    volumes:
      - ./frontend:/frontend
    ports:
      - 3000:3000
    env_file:
      - ./.env.dev
    environment:
      - WATCHPACK_POLLING=true
  backend:
    build:
      context: backend
    tty: true
    volumes:
      - ./backend:/backend
    ports:
      - 8000:8000
    depends_on:
      - db
    env_file:
      - ./.env.dev
  db:
    image: postgres
    env_file:
      - ./.env.dev
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:
```

### 環境変数用のファイルを作成
開発環境で用いる、環境変数をまとめた`.env.dev`ファイルを作成する。

```sh:.env.dev
# Next.JS
NEXT_PUBLIC_BE_BASEURL=http://localhost:8000

# Django
DEBUG=True
SECRET_KEY='[settings.pyからコピー]'
ALLOWED_HOSTS=127.0.0.1 localhost [::1]

DATABASE_NAME='sample_project'
DATABASE_USER='root'
DATABASE_PASSWORD='password'
DATABASE_HOST='db'
DATABASE_PORT='5432'

ALLOWED_ORIGINS=http://localhost:3000

# PostgreSQL
POSTGRES_USER=root
POSTGRES_PASSWORD=password
POSTGRES_DB=sample_project

# pgadmin4
PGADMIN_DEFAULT_EMAIL=XXXXX@xxx.com
PGADMIN_DEFAULT_PASSWORD=XXXXXXXXX
```
フロントエンド（Next.JS）で用いる環境変数は、`NEXT_PUBLIC_`を接頭につける必要がある。

### コンテナ群の起動
以下コマンドでコンテナを起動する
```bash
docker compose up -d
```

## 新規プロジェクトの作成
フロントエンド、バックエンドそれぞれのコンテナに入り、プロジェクトを新規作成する。
### バックエンド
コンテナの特定のために以下コマンドを実行する。
```bash:host
docker ps
```
コンテナIDの頭文字2文字をもとにバックエンドのコンテナに入る。
```bash:host
docker exec -it <コンテナIDの頭2文字> bash
```
Djangoプロジェクトを作成する（プロジェクト名: sample_project）
```bash:#backend
django-admin startproject sample_project .
```
`sample_project/settings.py`を以下のように変更する。
```python:settings.py
...(略)

LANGUAGE_CODE = 'ja'

...(略)

TIME_ZONE = 'Asia/Tokyo'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'sample_project',
        'USER': 'root',
        'PASSWORD': 'password',
        'HOST': 'db',
        'PORT': '5432',
    }
}
```
プロジェクトのルートディレクトリで以下コマンドを実行してアプリを立ち上げる。
```bash:#backend
python manage.py runserver 0.0.0.0:8000
```
[http://localhost:8000](http://localhost:8000)にアクセスして起動を確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628846/689e1d37-08ae-86d2-9065-ed4fab429cbe.png)


### フロントエンド
コンテナの特定のために以下コマンドを実行する。
```bash:host
docker ps
```
コンテナIDの頭文字2文字をもとにフロントエンドのコンテナに入る。
```bash:host
docker exec -it <コンテナIDの頭2文字> bash
```
Next.jsプロジェクトを作成する（プロジェクト名: sample_project）。
```bash:#frontend
npx create-next-app@latest sample_project --typescript
```
設定は以下のようにした（[参考にした記事](https://zenn.dev/ikkik/articles/51d97ff70bd0da)）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628846/293bb236-cb16-02d5-deb6-a5751c749f11.png)

プロジェクトのルートディレクトリに移動して、アプリを立ち上げる。
```bash:#frontend
cd sample_project
npm run dev
```
[http://localhost:3000](http://localhost:3000)にアクセスして起動を確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628846/aac2f805-a830-603a-6807-485d48b1b91d.png)

## 後編

CRUDアプリケーションの作成は次の記事で記載した。

https://qiita.com/ten-056/items/596984d532363c8dd4c8