フロントReact、サーバーNode(Express)、MySQLで開発をした話
先日開発を行った際のプロジェクト構成を、備忘録として残しておきます。
開発環境
- MacOS 12.2 M1 Processer (今回の環境はx64でも動作するようにしています)
- Docker
行いたかったこと
React&Nodeサーバー&MySQLコンテナを同時に起動させ、ReactとNodeコンテナをプロキシ経由で接続させて開発を行いました。
そして最終的に、EC2にデプロイさせるため、buildしたファイルをExpressサーバー上で動かすというところまで行いました。
まずは開発環境の構成から
フォルダ構成
今回のプロジェクト構成は以下になっております。
(一部抜粋)
.
├── backend
│ ├── app
│ │ ├── app.js
│ │ ├── .dockerignore //これ重要
│ │ ├── node_modules
│ │ ├── package.json
│ │ └── yarn.lock
│ └── dockerfile
│ └── Dockerfile
├── database
│ └── mysql
│ ├── dockerfile
│ │ └── Dockerfile
│ ├── my.cnf
│ └── sql
│ └── create_db.sql
├── docker-compose.yml
└── frontend
├── app
│ ├── .dockerignore //これ重要
│ ├── node_modules
│ ├── package.json
│ ├── public
│ ├── src
│ ├── tsconfig.json
│ └── yarn.lock
└── dockerfile
└── Dockerfile
docker-compose.ymlの構成
version: "3"
services:
express:
build: ./backend/dockerfile # Dockerfileの親フォルダパス
container_name: express-container # コンテナ名
hostname: express-server # ホスト名
tty: true
environment:
- NODE_ENV=DEVELOPMENT
- PORT=3001 # コンテナ内でのポート番号
volumes:
- ./backend/app:/usr/src/app
- express-data:/usr/src/app/node_modules # volumeのエントリポイント => 高速化
ports:
- 3001:3001 # 公開ポート番号:environmentで指定したポート番号
working_dir: /usr/src/app
command: sh -c "yarn install && yarn global add nodemon && nodemon app.js"
react:
build: ./frontend/dockerfile # Dockerfileの親フォルダパス
container_name: react-container # コンテナ名
hostname: react-server # ホスト名
tty: true
environment:
- NODE_ENV=DEVELOPMENT
- PORT=3000 # コンテナ内でのポート番号
volumes:
- ./frontend/app:/usr/src/app
- react-data:/usr/src/app/node_modules # volumeのエントリポイント => 高速化
ports:
- 3000:3000 # 公開ポート番号:environmentで指定したポート番号
working_dir: /usr/src/app
command: sh -c "yarn install && yarn start"
mysql:
build: ./database/mysql/dockerfile # Dockerfileの親フォルダパス
container_name: mysql-container # コンテナ名
hostname: mysql-server # ホスト名
platform: linux/x86_64
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
volumes:
- mysql-data:/var/lib/mysql # volumeのエントリポイント
- ./database/mysql/my.cnf:/etc/mysql/conf.d/my.cnf # cnfファイル
- ./database/mysql/sql/create_db.sql:/docker-entrypoint-initdb.d/create_db.sql # 起動時に実行するsqlファイル
environment:
MYSQL_ROOT_PASSWORD: password # rootユーザーのパスワード
TZ: Japan
ports:
- 3306:3306 # 公開ポート番号:3306(デフォルト値)
restart: always
volumes:
mysql-data:
name: db-data
express-data:
name: express-data
react-data:
name: react-data
コメントで書いてある通り、node_module
用のvolumeを作成しています。
これを作成しているかいないかで、読み込み速度が全然違います!
node_module
用のvolumeは必ず作成しておきましょう。
DockerFileの構成
React&Express
FROM node:16.13.2-alpine3.15
WORKDIR /usr/src/app
MySQL
今回はMySQL5.7
を使用しています。
当初8を使用していましたが、Nodeのライブラリと相性が合わなかったので。。。
# FROM mysql:latest
FROM mysql:5.7
RUN apt-get update -y && \
apt-get install -y locales && \
echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen && \
update-locale LANG=ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL=ja_JP.UTF-8
CMD ["mysqld", "--character-set-server=utf8", "--collation-server=utf8_unicode_ci"]
主に日本語設定を記述しています。
cnfファイルの内容は以下の通り。
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
default-time-zone = 'Asia/Tokyo'
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqldump]
default-character-set=utf8
同じような記述が多いので、もしかしたら必要ない箇所があるかもです。
.dockerignoreでnode_modulesを指定
node_modules/
この一行だけです。
ReactとExpressのプロジェクト配下に作成しましょう。
ReactからExpressに接続するためにプロキシを構成。
Reactプロジェクト内のpackage.json
に以下を追記します。
{
...
"proxy": "http://express-container:3001",
...
}
先ほどdocker-compose.yml
に記載したコンテナ名:ポート番号です。
AxiosなどでExpressにリクエストをする際は、
axios.get(`/api/...`)
の用に記述すればOK!
デプロイ時の構成
主な変更点は次のとおりです。
- Reactコンテナの排除
- Expressのポート番号変更
フォルダ構成
.
├── backend
│ ├── app
│ │ ├── app.js
│ │ ├── build // Reactのビルドデータ
│ │ ├── .dockerignore //これ重要
│ │ ├── node_modules
│ │ ├── package.json
│ │ └── yarn.lock
│ └── dockerfile
│ └── Dockerfile
├── database
│ └── mysql
│ ├── dockerfile
│ │ └── Dockerfile
│ ├── my.cnf
│ └── sql
│ └── create_db.sql
└── docker-compose.yml
docker-compose.ymlの構成
version: "3"
services:
express:
build: ./backend/dockerfile # Dockerfileの親フォルダパス
container_name: express-container # コンテナ名
hostname: express-server # ホスト名
tty: true
environment:
- NODE_ENV=PRODUCTION # 本番用設定
- PORT=3001 # コンテナ内でのポート番号
volumes:
- ./backend/app:/usr/src/app
- express-data:/usr/src/app/node_modules # volumeのエントリポイント => 高速化
ports:
- 80:3001 # 公開ポート番号:environmentで指定したポート番号
working_dir: /usr/src/app
command: sh -c "yarn install && node app.js" # 本番ではnodenv不要。
mysql:
build: ./database/mysql/dockerfile # Dockerfileの親フォルダパス
container_name: mysql-container # コンテナ名
hostname: mysql-server # ホスト名
platform: linux/x86_64
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
volumes:
- mysql-data:/var/lib/mysql # volumeのエントリポイント
- ./database/mysql/my.cnf:/etc/mysql/conf.d/my.cnf # cnfファイル
- ./database/mysql/sql/create_db.sql:/docker-entrypoint-initdb.d/create_db.sql # 起動時に実行するsqlファイル
environment:
MYSQL_ROOT_PASSWORD: password # rootユーザーのパスワード
TZ: Japan
ports:
- 3306:3306 # 公開ポート番号:3306(デフォルト値)
restart: always
volumes:
mysql-data:
name: db-data
express-data:
name: express-data
expressコンテナのポート番号を3001
から80
へ変更しています。
Expressのルーティング構成
私は今回以下のようなルーティングを行いました。
const express = require("express");
const app = express();
const router = require("express").Router();
...
// Dynamic resources rooting.
app.use("/api", router);
router.use("/user", require("./routes/user.js"));
/*
ルーティングをいくつか記述。
ルーティング処理を全て記述した最後に以下を記述。
*/
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, ".", "build", "index.html"));
});
このように処理を書いておくことで、/api以外のリクエストは全てindex.html
に流れるようになっています。
(404ページも含む)
EC2にデプロイして、インスタンスのURLにアクセスしてみよう!
Reactで作成したトップページが表示されればOKです。
私の場合、初回はログインページへ遷移するようにしていましたが、正常に動作しているようです!
/hogeでアクセスすると、
正常にNotFoundページも表示されました!
Discussion