GraphQL, Fastify, Nest, Prisma, MySQL, Docker環境をサクッと構築する
GraphQLが使えてPrismaが使えてDockerなバックエンド開発環境が欲しい!
TL;DR
GraphQL+node+RDBなバックエンド作成時にサクッと作り始められるテンプレートが欲しかったので作った。
最近TypeORMよりPrismaの方がいい感じっぽいのでPrismaもつっこんだ。
@nestjs/cli
をインストール
とりあえずnodeのバージョンを確認して ❯ node -v
v16.4.1
❯ npm -v
7.18.1
~~~~~~~~~~
❯ npm i -g @nestjs/cli
❯ nest new gql-nest-prisma
⚡ We will scaffold your app in a few seconds..
CREATE gql-nest-prisma/.eslintrc.js (631 bytes)
CREATE gql-nest-prisma/.prettierrc (51 bytes)
CREATE gql-nest-prisma/README.md (3339 bytes)
CREATE gql-nest-prisma/nest-cli.json (64 bytes)
CREATE gql-nest-prisma/package.json (1977 bytes)
CREATE gql-nest-prisma/tsconfig.build.json (97 bytes)
CREATE gql-nest-prisma/tsconfig.json (339 bytes)
CREATE gql-nest-prisma/src/app.controller.spec.ts (617 bytes)
CREATE gql-nest-prisma/src/app.controller.ts (274 bytes)
CREATE gql-nest-prisma/src/app.module.ts (249 bytes)
CREATE gql-nest-prisma/src/app.service.ts (142 bytes)
CREATE gql-nest-prisma/src/main.ts (208 bytes)
CREATE gql-nest-prisma/test/app.e2e-spec.ts (630 bytes)
CREATE gql-nest-prisma/test/jest-e2e.json (183 bytes)
? Which package manager would you ❤️ to use? npm
✔ Installation in progress... ☕
🚀 Successfully created project gql-nest-prisma
👉 Get started with the following commands:
$ cd gql-nest-prisma
$ npm run start
Thanks for installing Nest 🙏
Please consider donating to our open collective
to help us maintain this package.
🍷 Donate: https://opencollective.com/nest
サクッとExpress → Fastifyに変更
❯ npm i --save @nestjs/platform-fastify
/src/main.ts
を編集してFastifyを使うように設定
import { NestFactory } from '@nestjs/core';
+import {
+ FastifyAdapter,
+ NestFastifyApplication,
+} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
async function bootstrap() {
- const app = await NestFactory.create(AppModule);
+ const app = await NestFactory.create<NestFastifyApplication>(
+ AppModule,
+ new FastifyAdapter(),
+ );
await app.listen(3000);
}
bootstrap();
new FastifyAdapter()
は任意で new FastifyAdapter({ logger: true })
にしておくとログが出るので、 process.env.NODE_ENV
とかでロガーの設定とかを切り分けると良いのではないでしょうか。
サクサクGraphQLを設定
npm i @nestjs/graphql graphql-tools graphql apollo-server-fastify
import { Module } from '@nestjs/common';
+import { GraphQLModule } from '@nestjs/graphql';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
- imports: [],
+ imports: [GraphQLModule.forRoot({})],
controllers: [AppController],
providers: [AppService],
})
GraphQLModule.forRoot({
debug: true,
playground: true,
})
プロジェクトの内容や好みに合わせてGraphQLスキーマの生成の設定をする
- コードファーストでGQLのスキーマを自動生成する
- スキーマファーストで型定義を自動生成する
PrismaをORMとして使うのでサクサク設定していく
Prismaのインストールを行う
❯ npm install prisma --save-dev
Prismaの初期化をする
❯ npx prisma init
✔ Your Prisma schema was created at prisma/schema.prisma
You can now open it in your favorite editor.
Next steps:
1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlserver or sqlite.
3. Run prisma db pull to turn your database schema into a Prisma data model.
4. Run prisma generate to install Prisma Client. You can then start querying your database.
More information in our documentation:
https://pris.ly/d/getting-started
Prismaの設定をする
MySQLを使うので npx prisma init
で変更された .env
と生成された prisma/schema.prisma
を編集する
datasource db {
- privider = "postgresql"
+ provider = "mysql"
url = env("DATABASE_URL")
}
DATABASE_URL
を任意のDB接続設定に変更する
- DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
+ DATABASE_URL="mysql://root:@localhost:3306/mydb"
Dockerfile
と docker-compose.yml
を作成する
Nest, Prismaの設定に合わせて
Dockerfile
と docker-compose.yml
ファイルを作成
❯ touch Dockerfile docker-compose.yml
Dockerfile
に記述
アプリ用のnodeコンテナの設定を # ローカルと合わせておく
FROM node:16.4.1-alpine
# 任意のtime zone設定にする
ENV TZ=Asia/Tokyo
RUN apk --no-cache add tzdata && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /app
COPY package.json .
COPY package-lock.json .
RUN npm ci
EXPOSE 3000
ENTRYPOINT [ "npm", "run", "start:dev" ]
docker-compose.yml
でDBとアプリコンテナの設定
version: '3.7'
services:
api:
build:
context: .
dockerfile: Dockerfile
container_name: gql-nest-prisma #任意のコンテナ名
tty: true
stdin_open: true
volumes:
- .:/app
- /app/node_modules
depends_on:
- mydb
ports:
- '3000:3000'
mydb:
image: mysql:5.7
platform: linuxx86_64 # M1 Macだとこれ設定しないとちゃんと動かない
container_name: mysqldb
tty: true
stdin_open: true
volumes:
- ./db/dev:/docker-entrypoint-initdb.d
- ./db/my.cnf:/etc/mysql/conf.d/my.cnf
environment:
MYSQL_DATABASE: mydb
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
MYSQL_USER: user
MYSQL_PASSWORD: password # 任意のPWを設定する
TZ: Asia/Tokyo
# MYSQL_ROOT_PASSWORDは今回設定していないが必要に応じて設定する。
# .env の接続情報も編集すること
ports:
- '3306:3306'
Prisma Clientを導入する
参考
https://docs.nestjs.com/recipes/prisma#install-and-generate-prisma-client
❯ npm install @prisma/client
ここ( https://docs.nestjs.com/recipes/prisma#install-and-generate-prisma-client )を参考に prisma.service.ts
と main.ts
を設定する
import {
INestApplication,
Injectable,
OnModuleInit,
OnModuleDestroy,
} 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();
});
}
}
参考
https://docs.nestjs.com/recipes/prisma#issues-with-enableshutdownhooks
....
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
+import { PrismaService } from './prisma.service';
import { AppModule } from './app.module';
async function bootstrap() {
....
async function bootstrap() {
AppModule,
new FastifyAdapter(),
);
+ const prismaService: PrismaService = app.get(PrismaService);
+ prismaService.enableShutdownHooks(app);
await app.listen(3000);
}
bootstrap();
Let's Developing!
以上で環境の設定は終わりました!
docker-compose up
すれば開発サーバー&DBが立ち上がるかと思います。
ここから schema.prisma
にテーブル定義を構築したり、各種モジュールを作ったり、
GraphQLのスキーマを作ったりしていきましょう!!
また、バリデーションや認証設定したり、外部サービスを呼び出す場合はそれを作る必要もあります。
テストも書かないといけないでしょう。
NestJSのCLIやNestJSに最初から用意されている機能は非常に強力なので、それらを使えばサクサクと開発を進めていけるはずです。
nodeバックエンドなんもわからん。 の自分でもサクッと環境が作れてバックエンドの開発に集中できる環境が作れました。
dockerに乗ってるのでプロダクションリリースも楽ちんです。
実際にプロダクト開発で使う際には
ドキュメント生成や、
huskyを使った整形、テストなどの自動化を設定したりしても開発体験をガンガン上げていけると思います。
手元とコンテナ内のnodeのバージョンを合わせるために asdf
の.tool-versions
を設定したりしてたりもします。
時間が取れたら続きとして実際にGraphQLのAPIを立ててPlaygroundでCRUDしてみた記事を投稿するかもしれません。
参考にしたドキュメントなど
nestjs公式ドキュメント
prisma.io/nestjs
prismaのnestjs-graphqlリポジトリ
fivethree-team/nestjs-prisma-starter
NestJS導入 husky編
Discussion