イントロダクション
環境構築編では、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のシークレットキーを記述します。今のところは以下で大丈夫です。
SECRET_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
DEBUG=False
続いて、開発環境用のpythonのDockerfileです。
# 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に必要なモジュールです。
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の中身になります。
#!/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です。
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の中身になります。
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です。
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サーバーへの設定
[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の中身です。
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の設定をしていきます。
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のデフォルトページが表示されれば成功です。