この記事で達成したいこと
- Express + Dockerの環境構築
- 上記環境にSequelizeをインストール
- SequelizeでDBに接続する
Express + Dockerの環境構築
タイトルと若干乖離しているが、
本記事の目的は、
Sequelizeの使い勝手を試してみるということにある。
ただ、試すといっても、
土台の環境がないと難しい。
そこでまずは、Expressで簡単なAPIサーバーを立てるとこから始める。
環境によって動かないみたいなことをなくしたいので、
Dockerはやはり必須だ。
まずは、こんな感じのディレクトリ構成を作る。
-docker-compose.yml
-express
|--Dockerfile
|--package.json
|--src
|--index.ts
docker-compose.ymlと同階層にDockerfileを作成してもいいが、
後々フロントにReactとかVueを入れることなども想定すると、
フロントとバックそれぞれでDockerfileが必要になるので、
このようにバックエンドのディレクトリ直下に入れたほうが、
後にディレクトリ構造を変更しなくて済む場合が多い。
(まあ本記事ではReactとかは入れないので、余計な配慮かもしれないが)
さて、Dockerfileとdocker-compose.ymlはとりあえず、
下記のようにしてみる。
FROM node:16.13.1-alpine
WORKDIR /usr/src/app
COPY ./package* ./
RUN apk update && \
apk add mysql-client
RUN npm install @types/express
RUN npm install
COPY . .
EXPOSE 3002
CMD npm start
version: '3'
services:
express:
build: ./express
volumes:
- ./express:/usr/src/app
- /usr/src/app/node_modules
command: npm start
depends_on:
- "mysql"
ports:
- "3002:3002"
networks:
- db-net
mysql:
image: "mysql:5.7.40-debian"
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- "3306:3306"
networks:
- db-net
environment:
MYSQL_ROOT_PASSWORD: "admin"
MYSQL_USER: "user"
MYSQL_PASSWORD: "password"
MYSQL_DATABASE: "db"
platform: linux/x86_64
networks:
db-net:
driver: bridge
上記のDockerfileでpackage.jsonのCopy命令を出しているので、
package.jsonも作成する必要がある。
copy命令を出さないで、
コンテナ内に入って、npm installとかをして、
package.jsonを作る方法でもいいのだが、
gitでcloneとかしてきたときは、
docker compose build, upだけで
環境構築が完了するやり方のほうが、
いいと思うので、ここでは予めpackage.jsonを用意するパターンにする。
とりあえず、package.jsonにはexpressが入っていれば問題ないが、
一旦こんな感じにしてみる。
{
"dependencies": {
"express": "^4.17.2",
"mysql": "^2.14.1"
},
"devDependencies": {
"@types/node": "^16.11.10",
"jest": "^29.3.1",
"ts-node": "^10.9.1",
"typescript": "4.5.2"
},
"scripts": {
"start": "ts-node src/index.ts",
"test": "jest"
}
}
上記のdocker-compose.ymlの中で、
expressのcommandがnpm startになっていた。
services:
express:
省略
command: npm start
すなわち、docker compose upするときに、
上記のnpm startが対象コンテナに対して実行されるということだが、
肝心のpackage.jsonのstartコマンドを見てみると、
"scripts": {
"start": "ts-node src/index.ts",
"test": "jest"
}
src/index.tsに対して実行していることがわかる。
そのため、このindex.tsも作成する必要がある。
そして、このファイルはexpressのサーバーを立ち上げるファイルなので、
とりあえず、expressの公式のコードを参考にこんな感じにしてみる。
import express, { Request, Response } from "express";
const app = express();
const port = 3002;
app.get("/", (req: Request, res: Response) => {
res.send("Hello World");
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
TypeScriptなので、Request型とResponse型をimportしていること以外は、
基本jsファイルのときと変わらない。
さて、これで動くはずだ。
docker compose build
docker compose up
コンテナが立ち上がって、
localhost:3002にアクセスして、
Hello Worldが返ってくれば、
サーバーが立ち上がっている。
Sequelizeをインストール
sequelizeを動かす土台はできたので、
早速本題のsequelizeのインストールを行う。
ドキュメントだと微妙に分かりづらい箇所に書かれているが、
Railsのようにcliでの操作が色々できるようだ。
まずは、先程作ったのexpressのコンテナの中に入る。
d compose exec express /bin/ash
本体、mysql2とcliをインストールする
npm install --save sequelize
npm install --save mysql2
npm install --save-dev sequelize-cli
インストールできたら、
次のコマンドで新規プロジェクトを立ち上げることができる。
Railsでいう、rails newにあたると思われる。
npx sequelize-cli init
config/config.jsonなどのファイルが作成される。
最初は、こんな風に記述されているだろう。
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
こちらをdocker-compose.ymlで定義したmysqlのコンテナと
情報を合うように修正する。
DBを作成する前に、一旦DBのコンテナに入って中身を確認してみる。
docker compose exec mysql /bin/bash
mysqlにログインして、現在あるDBを確認したところ、
information_schemaしかなく、
config.jsonで設定したDBはつくられていないことがわかる。
上記のdocker-compose.ymlのDB設定と合わせて、
config.jsonを設定すると、
こんな感じになる。
{
"development": {
"username": "user",
"password": "password",
"database": "db",
"host": "mysql",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
※testとproductionの設定はいじっていない。
そのため、SequelizeでDBを作成したら、
上記のdbという名前のDBが作成されていたら、
dockerのdbとSequelizeが疎通できていることが確認できる。
早速、データベースを作成して試してみる。
※express側のコンテナに入ってから下記コマンドを実行してください
npx sequelize-cli db:create
作成したらもう一度dbのコンテナに入って作成されているか確認してみる。
docker compose exec mysql /bin/bash
ちゃんとdbというデータベースが作成されていることが確認できた。
Modelを作成してみる
さて、以上の流れで一応DBとの接続は確認できたが、
せっかくなので適当にモデルを作ってmigrationまでやってしまいたい。
ドキュメントに従って、
無難にUserモデルを作ってみる。
npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string
どうやら上記のコマンドはRailsに似ており、
上記コマンドでmigrationファイルが作成されるようである。
(上記コマンド実行時点ではDB上にテーブルは作成されない)
となれば、次にやることは決まっている。
そうmigrationだ。
npx sequelize-cli db:migrate
Userテーブルが作成され、
モデル作成コマンドの際に指定したカラム構成になっていることが確認できた。
Sequelizeを使ってみた印象
個人的にはかなりRailsライクで使いやすかったと思う。
本記事では試さなかったが、seedなどもあり、
TypeORMなどと比べると、
かなりRailsエンジニアに優しい感じだった。
もちろん、まだ細かい検証とかしていないので、
残りは実際になんか適当なアプリを作成してみて、
もっと詳しい使い勝手を探求してみたい。