Nest.js + MySQL + Prismaの環境構築

最近TypeScriptでバックエンドを構築するとなるとNest.jsが候補に上がることが増えましたよね。

Nest.jsはNode.jsベースの効率的でスケーラブルなサーバーサイドアプリケーションを構築するためのフレームワークです。

特徴としては下記があります。

  • TypeScriptを完全にサポートしており、型安全性の高いコードを書くことができる
  • Expressをベースにしており、Expressのエコシステムとライブラリをそのまま活用できる
  • モジュール、コントローラー、プロバイダーなどの概念を用いた整理された構造が提供される
  • 依存性注入を採用しており、疎結合で保守性の高いコードを書くことができる
  • REST API、GraphQL、WebSocketsなど様々なタイプのアプリケーションに対応している
  • マイクロサービスアーキテクチャの構築にも適している

今回作る環境

  • Docker + Docker Compose
  • Nest.js
  • eslint
  • MySQL
  • Prisma

使用環境

  • M2 Mac
  • Docker 24.0.5
  • Docker Compose v2.20.2-desktop.1

セットアップ

1, 適当なディレクトリを作る

mkdir nestjs-test
cd nestjs-test

2, 構築に必要なファイル類作成

touch Dockerfile docker-compose.yml .env

▼Dockerfile

FROM node:18.16.0-slim
RUN apt-get update && \\
    apt-get install -y locales curl
RUN locale-gen ja_JP.UTF-8
RUN localedef -f UTF-8 -i ja_JP ja_JP
ENV LANG=ja_JP.UTF-8
ENV TZ=Asia/Tokyo
WORKDIR /app

▼docker-compose.yml

version: '3.7'
services:
  app:
    build: .
    tty: true
    ports:
      - 5000:5000
    volumes:
      - .:/app
      - /app/node_modules
    depends_on:
      - mysql
  mysql:
      image: mysql:8.0
      container_name: mysql
      volumes:
        - ./mysql-data:/var/lib/mysql
      ports:
        - 3306:3306
      environment:
        MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
        MYSQL_DATABASE: ${MYSQL_DATABASE}
        MYSQL_USER: ${MYSQL_USER}
        MYSQL_PASSWORD: ${MYSQL_PASSWORD}

▼.env

MYSQL_ROOT_PASSWORD=test
MYSQL_DATABASE=test
MYSQL_USER=test
MYSQL_PASSWORD=test

コンテナ立ち上げ

docker compose up -d

MySQLでDBが作られているか確認

1, MySQLコンテナにログイン

docker compose exec mysql bash

2, MySQL環境にログイン

パスワードは.envで設定したやつ(今回はtest)

DBが存在しているのを確認

bash-4.4# mysql -u test -p

Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \\g.
Your MySQL connection id is 9
Server version: 8.0.34 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| performance_schema |
| test               |
+--------------------+
3 rows in set (0.03 sec)

3, MySQL環境、MySQLコンテナからログアウト

mysql> exit
bash-4.4# exit

Nest.jsセットアップ

1, Nest.jsコンテナにログイン(以降はコンテナ内で作業)

docker compose exec app bash

2, Nest CLIをインストール

root@d49546474b23:/app# npm install -g @nestjs/cli

3, プロジェクト作成

現在ディレクトリ内(gms-test)で作成。—strictオプションを付けるとtypescriptでの厳格な型チェックを利用できる

root@d49546474b23:/app# nest new --strict .

パッケージマネージャーはお好みで

? Which package manager would you ❤️  to use? (Use arrow keys)
❯ npm
  yarn
  pnpm

プロジェクトが作成される

? Which package manager would you ❤️  to use? npm
CREATE .eslintrc.js (663 bytes)
CREATE .prettierrc (51 bytes)
CREATE README.md (3340 bytes)
CREATE nest-cli.json (171 bytes)
CREATE package.json (1944 bytes)
CREATE tsconfig.build.json (97 bytes)
CREATE tsconfig.json (541 bytes)
CREATE src/app.controller.spec.ts (617 bytes)
CREATE src/app.controller.ts (274 bytes)
CREATE src/app.module.ts (249 bytes)
CREATE src/app.service.ts (142 bytes)
CREATE src/main.ts (208 bytes)
CREATE test/app.e2e-spec.ts (630 bytes)
CREATE test/jest-e2e.json (183 bytes)

✔ Installation in progress... ☕

🚀  Successfully created a new project
👉  Get started with the following commands:

$ cd .
$ npm run start

Failed to execute command: git init
Git repository has not been initialized

                          Thanks for installing Nest 🙏
                 Please consider donating to our open collective
                        to help us maintain this package.

               🍷  Donate: <https://opencollective.com/nest>

ESlintインストール

1, eslintインストール

広く使われているらしいairbnbの設定をインストールしてみる

root@d49546474b23:/app# npm install --dev eslint-config-airbnb-base eslint-plugin-import eslint-config-airbnb-typescript

2, 設定を修正

▼.eslintrc.js

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'tsconfig.json',
    tsconfigRootDir: __dirname,
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint/eslint-plugin'],
  extends: [
    'airbnb-base',
    'plugin:@typescript-eslint/recommended',
    'airbnb-typescript/base',
    'plugin:prettier/recommended',
  ],
  root: true,
  env: {
    node: true,
    jest: true,
  },
  ignorePatterns: ['.eslintrc.js'],
  rules: {
    '@typescript-eslint/interface-name-prefix': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    'class-methods-use-this': 'off',  // staticに関するエラーを無視する
    'import/prefer-default-export': 'off',  // default-exportのエラーを無視する
  },
};

Prismaセットアップ

1, Prismaをインストール

PrismaはTypeScript製のORMマッパー。TypeScriptライクにスキーマの定義や、DBの操作が可能で便利。

typescriptの設定も一緒にインストールしてあげる

root@d49546474b23:/app# npm install --save-dev prisma typescript ts-node @types/node

2, 初期化

プロジェクトにprismaディレクトリとschema.prismaが作成される

root@d49546474b23:/app# npx prisma init

3, 使用DBをMySQLに設定

デフォルトはPostgreSQLになっているのでMySQLに変える

▼schema.prisma

datasource db {
  provider = "postgresql" // mysqlに変える
  url      = env("DATABASE_URL")
}

schema.prismaはVScodeデフォルトだとハイライトされないので拡張機能を入れておくと便利。

また、初期化時に.envに下記が追加されているのでDATABASE_URLもMySQL用に変えておく。

▼.env

# This was inserted by `prisma init`:
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: <https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema>

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: <https://pris.ly/d/connection-strings>

// DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
DATABASE_URL="mysql://root:test@mysql:3306/test"

.envDATABASE_URLの指定は下記のフォーマットになっているが、 `DATABASE_URL="mysql://{ユーザー}:{パスワード}@{ホスト}:{ポート}/{データベース名}"` Dockerを使う場合ホストの指定はdocker-compose.ymlでMySQL用コンテナのコンテナ名として指定した文字列が指定できる。 いつものノリでlocalhostとするとこの後appコンテナからマイグレートする時エラーになる。 (appコンテナから見たlocalhostはappコンテナになるため)

4, スキーマを定義

今回は簡単にUserテーブルを定義する

▼schema.prisma

...

model User {
  id    Int     @default(autoincrement()) @id
  email String  @unique
  name  String
}

5, スキーマをマイグレート

root@d49546474b23:/app# npx prisma migrate dev --name init

migrationsディレクトリとマイグレートファイルが作成される

migrations/
  └─ 20231006012540_init/
    └─ migration.sql

6, Userテーブルが作成されていることを確認

docker compose exec mysql bash
bash-4.4# mysql -u test -p

mysql> show databases;
mysql> use test;
mysql> show tables;
+--------------------+
| Tables_in_test     |
+--------------------+
| _prisma_migrations |
| User               |
+--------------------+
3 rows in set (0.01 sec)

以上でDocker + Nest.js + MySQL + eslint + Prismaの環境が完成です。

おわり

Nest.jsは特に大規模なエンタープライズアプリケーションの開発に適しており、TypeScriptの利点を活かしつつ、整理された構造でスケーラブルなバックエンドを構築したい場合に良い選択肢となります。

この機会にぜひ色々触ってみてください。