LoginSignup
8
8

More than 1 year has passed since last update.

モダンなWebアプリ(Django, Next.js, Docker, AWS)を開発する #環境構築編

Last updated at Posted at 2023-03-02

イントロダクション

環境構築編では、docker-composeを使ってDjango, Next.js, MySQL, Nginxの環境を同時に立ち上げられるようにしていきます。
バックエンドはAWS ECSに、フロントエンドはVercelにデプロイする予定なので、そのことを前提に環境構築を進めていきます。

!この記事の内容は今後推敲し修正、追加していくつもりなので、内容の変更にご注意ください。

参考元の記事はこちらになります↓
DockerでReact+Django+Nginx+MySQLの環境構築

構築の流れ

  • バックエンドの構築
    djangoの構築
    nginxの構築
    mysqlの構築
    docker-composeの設定
  • フロントエンドの構築
    Next.jsの構築
    docker-composeの設定

環境構築

最終的なディレクトリ構成は以下のようになります。

Todo
├── backend
│   ├── api
│   └── nginx
├── frontend
│   └── app
├── mysql
├── mysql_volume
├── sql
└── docker-compose.yml

Backendの構築

まずはフォルダーを作成していきます。以下のコマンドを実行してください。

mkdir Todo && cd Todo
mkdir backend
mkdir backend/api backend/nginx
mkdir frontend
mkdir frontend/app
mkdir mysql
mkdir mysql_volume
mkdir sql
touch docker-compose.yml

treeコマンドで確認できます。

tree .

treeをインストールしていない方(mac)は下記で実行できるようになります。

brew install tree

Djangoの構築

backend/apiにdjangoプロジェクトを作成していきます。

cd backend/api
touch .env Dockerfile.dev requirements.txt entrypoint.dev.sh

.envファイルにはDjangoのシークレットキーを記述します。今のところは以下で大丈夫です。

.env
SECRET_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
DEBUG=False

続いて、開発環境用のpythonのDockerfileです。

Dockerfile.dev
# backend/api/Dockerfile.dev
FROM python:3.7  #1

ENV PYTHONDONTWRITEBYTECODE 1  #2
ENV PYTHONUNBUFFERED 1

WORKDIR /usr/src/app  #3

COPY ./entrypoint.dev.sh ./usr/src/app/  #4
COPY ./requirements.txt ./usr/src/app/
RUN python3 -m pip install --upgrade pip setuptools
RUN pip install -r ./usr/src/app/requirements.txt

RUN chmod +x ./usr/src/app/entrypoint.dev.sh  #5

COPY . ./usr/src/app/  #6

ENTRYPOINT ["sh", "entrypoint.dev.sh"]  #7

EXPOSE 8000  #8

内容の解説です。
#1 リモートのpythonイメージをインストール
#2 環境変数を設定
#3 コンテナ内の作業ディレクトリを決定
#4 ホスト内の各ファイルをコンテナ内の作業ディレクトリにコピー
#5 entrypoint.dev.shに権限を付与
(これが無いとECSデプロイ時の権限にエラーになります。)
#6 ホスト内のdjangoプロジェクトをコンテナ内の作業ディレクトリにコピー
#7 ENTRYPOINT(コンテナ起動時に実行したいコマンド)の指定
#8 Djangoで使用したいポートを指定

続いて、Djangoに必要なモジュールです。

requirements.txt
asgiref==3.2.10
certifi==2020.12.5
dj-database-url==0.5.0
dj-static==0.0.6
Django==3.1
django-cors-headers==3.4.0
django-templated-mail==1.1.1
djangorestframework==3.11.1
djangorestframework-simplejwt==4.6.0
djoser==2.0.3
PyJWT==2.0.0
python-decouple==3.3
pytz==2020.5
sqlparse==0.4.1
static3==0.7.0
gunicorn==20.0.4
python-dotenv==0.13.0
mysqlclient==2.0.2

entrypoint.dev.shの中身になります。

entrypoint.dev.sh
#!/bin/sh

gunicorn config.wsgi:application --bind 0.0.0.0:8000
exec "$@"

最初と最後はおまじないです。
真ん中はgunicornの設定で、のちにconfigというdjangoプロジェクトを作成するので、そのconfig内のwsgi.pyを指定している形になります。
--bindというのは、GunicornのListenポートとして待ち受けるポートであり、ネットワーク:ポートで記述します。0.0.0.0にbindすることで、どの環境からでもアクセスを受け付けられるようにしています。
今はgunicornの設定だけですが、ここに python manage.py makemigrationsなどを記述していきます。

Nginxの構築

backend/nginxにnginxを作成していきます。

cd ../nginx
touch Dockerfile.dev default.dev.conf

開発環境用のnginxのDockerfileです。

nginx/Dockerfile.dev
FROM nginx:1.17.4-alpine  #1

RUN rm /etc/nginx/conf.d/default.conf  #2
COPY default.dev.conf /etc/nginx/conf.d/default.dev.conf  #3

CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf  #4

内容の解説です。
#1 リモートのnginxイメージをインストール
#2 nginxのデフォルト設定ファイルを削除
#3 代わりに自作したnginx設定ファイルをコンテナ内にコピー
#4 CMDでnginxを起動

default.dev.confの中身になります。

nginx/default.dev.conf
upstream django {
    server api:8000;
}

server {
    listen 80;
    location / {
        proxy_pass http://django;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
    }
    location /static/ {
        alias /usr/src/app/static/;
    }
}

MySQLの構築

本番環境ではAWS RDSを使うので、ローカルのmysqlは使い捨てになります。
backend/mysqlにmysqlを作成していきます。

cd ../../mysql
touch Dockerfile my.cnf

mysqlのDockerfileです。

mysql/Dockerfile
FROM mysql:8.0.0

RUN echo "USE mysql;" > /docker-entrypoint-initdb.d/timezones.sql &&  mysql_tzinfo_to_sql /usr/share/zoneinfo >> /docker-entrypoint-initdb.d/timezones.sql

COPY ./my.cnf /etc/mysql/conf.d/my.cnf

ここの設定をいじることはないので、内容は省略します。

mysqlの設定ファイルです。

mysql/my.cnf
# MySQLサーバーへの設定
[mysqld]
# 文字コード/照合順序の設定
character_set_server=utf8mb4
collation_server=utf8mb4_bin

# タイムゾーンの設定
default_time_zone=SYSTEM
log_timestamps=SYSTEM

# デフォルト認証プラグインの設定
default_authentication_plugin=mysql_native_password

# mysqlオプションの設定
[mysql]
# 文字コードの設定
default_character_set=utf8mb4

# mysqlクライアントツールの設定
[client]
# 文字コードの設定
default_character_set=utf8mb4

続いて、SQLフォルダに移動しinit.sqlを作成します。

cd ../sql
touch init.sql

init.sqlの中身です。

sql/init.sql
GRANT ALL PRIVILEGES ON test_todoList.* TO 'user'@'%';

FLUSH PRIVILEGES;

GRANTでuserにtest_todoListテーブルへの権限を与えています。
FLUSH PRIVILEGESでデータベース内のGRANTテーブルを再読込します。 mysqlはキャッシュに権限等を保持しており、この情報を最新化するためにFLUSH PRIVILEGESを実行します。

ここまででファイルはこのようになっているはずです。

cd ..
tree -a
.
├── backend
│   ├── api
│   │   ├── .env
│   │   ├── Dockerfile.dev
│   │   └── requirements.txt
│   └── nginx
│       ├── Dockerfile.dev
│       └── default.dev.conf
├── docker-compose.yml
├── frontend
│   └── app
├── mysql
│   ├── Dockerfile
│   └── mysql.cnf
├── mysql_volume
└── sql
    └── init.sql

9 directories, 9 files

docker-composeの設定

docker-composeの設定をしていきます。

docker-compose.yml
version: "3.7"

services:
  api:
    container_name: python-backend
    env_file: ./backend/api/.env
    build:
      context: ./backend/api/.
      dockerfile: Dockerfile.dev
    volumes:
      - ./backend/api:/usr/src/app/
      - static_volume:/usr/src/app/static # <-- bind the static volume
    stdin_open: true
    tty: true
    networks:
      - backend_network
    environment:
      - CHOKIDAR_USEPOLLING=true
      - DJANGO_SETTINGS_MODULE=config.local_settings
    depends_on:
      - db
  backend-server:
    container_name: nginx_backend
    build:
      context: ./backend/nginx/.
      dockerfile: Dockerfile.dev
    volumes:
      - static_volume:/usr/src/app/static # <-- bind the static volume
    ports:
      - "8080:80"
    depends_on:
      - api
    networks:
      - backend_network
  db:
    build: ./mysql
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: todoList
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      TZ: "Asia/Tokyo"
    volumes:
      - ./mysql_volume:/var/lib/mysql
      - ./sql:/docker-entrypoint-initdb.d
    networks:
      - backend_network
networks:
  backend_network:
    driver: bridge
volumes:
  static_volume:

内容が多いですが、慣れてしまえば簡単です。
大まかにapi, backend-server, dbの3つに分けられます。
それぞれpython, nginx, mysqlのdockerfileに該当しています。

contianer_name: コンテナの名前
env_file: envを指定
build: Dockerfile.devへのパスとファイルを指定
volumes: 後述
stdin_open: docker run -it {container_name}の-iにあたる設定
tty: docker run -it {container_name}の-tにあたる設定
networks: コンテナのネットワーク設定
environment: 環境変数等の設定
depends_on: 依存関係の設定(今回だとdbが起動した後にapiを起動させる)
ports: {ホストのポート}:{コンテナのポート}をつなぐ
command: コンテナ起動時に実行したいコマンドの指定(dockerfileのentrypointと同じ)

* docker run -it {container_name} bashはコンテナ内に入るためのコマンドです。
stdin_openやttyはそのために必要な設定です。
docker-compose.yml個人的Tips集
stdin_openやtty、volumeについて、詳しくはこちらを参考にしてください。

ここまでの設定ができたら、いよいよdjangoプロジェクトとアプリを作成していきます。

docker-compose run --rm api sh -c "django-admin startproject config ."

docker-compose run --rm api sh -c "python manage.py startapp todo"

backend/api配下がこのような構成になると思います。

tree .
.
├── Dockerfile.dev
├── config
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── entrypoint.dev.sh
├── manage.py
├── requirements.txt
└── todo
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── serializers.py
    ├── tests.py
    ├── urls.py
    └── views.py

アプリが動くかを確認します。

docker-compose up --build

localhost:8080にアクセスしてブラウザにdjangoのデフォルトページが表示されれば成功です。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8