はじめに
この記事では、NestJsを使ってAPI開発したいという方に向けて記事を作成しています。
ソースを載せておくのでご自由にお使いください。
目次
1.ディレクトリイメージ
2.Dockerfileとdocker-compose.ymlの作成
3.Nestプロジェクトをdockerコンテナのワーキングディレクトリに作成
4.MySQLイメージ追加
5.Prismaを利用してMySQLと接続する
1. ディレクトリイメージ
project-path
|- docker-compose.yml
|- Dockerfile
|- .dockerignore
|- nestのmodule達
2. Dockerfileとdocker-compose.ymlの作成
FROM node:14.17
RUN npm i -g @nestjs/cli
WORKDIR /api
version: '3.7'
services:
nest:
container_name: nestjs_demo
build: .
tty: true
ports:
- '3000:3000'
volumes:
- type: bind
source: .
target: /api
node_modules
nodeイメージをベースにして、@nestjs/cliをインストール
ビルド
% docker compose up -d --build
% docker compose ps
3. Nestプロジェクトをdockerコンテナのワーキングディレクトリに作成
% docker compose exec nest nest new .
? Which package manager would you ❤️ to use? (Use arrow keys)
❯ npm
yarn
pnpm
と聞かれるので、今回はnpmを選択します。
% docker compose exec nest npm run start:dev
http://localhost:3000/
にアクセスして、Hello World!と表示されたら、起動成功です。
このコマンドを毎回打つのは面倒なのでnestコンテナに
このコマンドを追加してビルドし直します。
FROM node:14.17
RUN npm i -g @nestjs/cli
WORKDIR /api
# ここから追加
COPY package*.json /api/
RUN npm i
CMD [ "npm", "run", "start:dev"]
# ここまで追加
docker compose up -d --build
4. MySQLイメージ追加
docker-compose.ymlに追記して、MySQLコンテナを立ち上げる
version: '3.7'
services:
nest:
container_name: nest
build: .
tty: true
ports:
- '3000:3000'
volumes:
- type: bind
source: .
target: /api
depends_on: # 追加
- db
db:
platform: linux/x86_64
image: mysql:5.7
container_name: nestjs-demo-db
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: nestjs_demo
MYSQL_PASSWORD: root
TZ: 'Asia/Tokyo'
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
ports:
- 3306:3306
phpmyadmin:
container_name: nestjs-demo-phpmyadmin
image: phpmyadmin/phpmyadmin
environment:
- PMA_ARBITRARY=1
- PMA_HOSTS=nestjs-demo-db
- PMA_USER=root
- PMA_PASSWORD=root
ports:
- 8080:80
DB設定のためのmy.cnfを作成
ルートディレクトにdockerディレクトリ、その中にdbディレクトリを作成してその中に作成します。
これが、docker volumeマウントされます
[mysqld]
default-authentication-plugin=mysql_native_password
character-set-server=utf8mb4
[mysql]
default-character-set=utf8mb4
[client]
default-character-set=utf8mb4
.env追加・編集
DATABASE_URL="mysql://root:root@nestjs-demo-db:3306/nestjs_demo"
DBが作成されているか確認
% docker compose up
MySQLの管理ツールphpmyadminのimageを入れたので
http://localhost:8080/
にアクセスすればDBの確認ができます。
「nestjs_demo」というDBができていれば成功です。
5. Prismaを利用してMySQLと接続する
続いて、Prismaを利用するためのセットアップを行います。
% docker compose run nest npm install --save-dev prisma
% docker compose run nest npx prisma init
この時点で、prismaというフォルダが作成されます。
prismaフォルダの中にschema.prismaがあり、
それを編集していくことで、DBのモデルを作成していきます。
prismaスキーマファイル編集
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
password String
registered_at DateTime @default(now())
updated_at DateTime @updatedAt
roles AdminAccountRole[]
@@map("users")
}
mysqlを使うのでpostgresqlから変更
usersという名前でmysqlのデータベースに作成
prismaスキーマファイルのマイグレート
% docker compose run nest npx prisma migrate dev --name init
-- CreateTable
CREATE TABLE `users` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(191) NOT NULL,
`email` VARCHAR(191) NOT NULL,
`password` VARCHAR(191) NOT NULL,
`registered_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `users_email_key`(`email`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
生成されたマイグレーションファイル
PrismaClientのインストール
% docker compose run nest npm install @prisma/client
Prisma Clientは、Prismaのモデル定義から生成されるタイプセーフのデータベースクライアントです。
インストール時に、Prismaは自動的にprisma generateコマンドを呼び出します。
なので、次回以降Prismaモデルを変更するたびにこのコマンドを実行し、生成されたPrismaクライアントを更新する必要があります。
Prisma Client service作成
docker-compose run nest nest generate service Prisma
PrismaClientのインスタンス化とデータベースへの接続を行うPrismaService
srcディレクトリ内にprisma.service.tsというファイルを新規に作成し、下記のコードを追加します。
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
}
Users service作成
docker-compose run nest nest generate service users
Prismaスキーマから、先程作成したUserモデルのデータベースを呼び出すために使用するUsersServiceを作成します。
srcディレクトリの中にusersディレクトリとusers.service.tsというファイルを新規に作成し、下記のコードを追加します。
import { Injectable } from '@nestjs/common';
import { PrismaService } from './../prisma/prisma.service';
import { User, Prisma } from '@prisma/client';
@Injectable()
export class UsersService {
constructor(private prisma: PrismaService) {}
async user(id: number): Promise<User | null> {
return this.prisma.user.findUnique({
where: { id },
});
}
async users(): Promise<User[]> {
return this.prisma.user.findMany();
}
async createUser(data: Prisma.UserCreateInput): Promise<User> {
return this.prisma.user.create({
data,
});
}
}
ルーティングとコントローラを追加
% docker-compose run nest nest g controller users
続いて、先程作成したサービスを使用して、ルーティングとコントローラを定義します。
usersディレクトリの中にusers.controller.tsというファイルを新規に作成し、下記のコードを追加します。
import { Controller, Get, Param, Post, Body } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from '@prisma/client';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get(':id')
async findUserById(@Param('id') id: string): Promise<User> {
return this.usersService.user(Number(id));
}
@Get()
async users(): Promise<User[]> {
return this.usersService.users();
}
@Post()
async createUser(
@Body() userData: { name: string; email: string; password: string },
): Promise<User> {
return this.usersService.createUser(userData);
}
}
Usersモジュールを追加
% docker-compose run nest nest g module users
最後にUsersModuleを作成し、AppModuleに追加します。
users配下にusers.module.tsというファイルを作成し、下記コードを追加します。
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { PrismaService } from './../prisma/prisma.service';
@Module({
controllers: [UsersController],
providers: [UsersService, PrismaService],
})
export class UsersModule {}
app.module.tsにUsersモジュールをimport
※基本generateコマンドでファイルを生成した場合はその時点で自動的にここに追加されます
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PrismaService } from './prisma/prisma.service';
import { UsersService } from './users/users.service';
import { UsersController } from './users/users.controller';
import { UsersModule } from './users/users.module';
@Module({
imports: [UsersModule], // 追加
controllers: [AppController, UsersController],
providers: [AppService, PrismaService, UsersService],
})
export class AppModule {}
これでNest.jsにPrismaを導入し、アプリケーションからDBを操作できるようになりました
curl コマンドでAPIの動作確認
% curl -H "content-type: application/json" -X POST -d'{"name":"test", "email":"test@sample.com", "password":"12345678"}' http://localhost:3000/users
→usersコントローラcreateUserアクション実行
% curl -X GET http://localhost:3000/users/1
→usersコントローラfindUserByIdアクション実行
% curl -X GET http://localhost:3000/users
→usersコントローラusersアクション実行
POST後のデータ確認時はMySQLの管理ツールphpmyadminでも確認できます。
http://localhost:8080/
以上です