ども!年末年始の検証結果を順次ブログ化している龍ちゃんです。思いついたらすぐ検証という流れで、いろんなことを検証していたので10本ぐらいはブログのネタに困らなさそうですね。反動が今から恐ろしいです。
今回の内容は、以下の二つになります。
- ローカル開発環境をDevContainerで作成する(nest.js + postgres)
- nest.jsからPrismaを使用してpostgresに接続する
今回のゴールとしては、nest.js内でORMとしてPrismaを使用してpostgresへ接続して動作確認となります。
環境構築
前提条件としては、DockerとDocker Composeコマンドが使えれば大丈夫です。最終的なファイルとしては、こちらのリポジトリに上がっています。まだ、絶賛開発に使用する前段階なので、何の整備もしていなくてすいません。
ディレクトリ構成としては、以下のようになります。postgresのデータの永続化は、ボリュームマウントとしてコンテナ内へ収めておきます。
.
├── .devcontainer
│ └── devcontainer.json
├── .dockerignore
├── .env # docker用環境変数
├── Dockerfile
├── docker-compose.yml
└── nest-app # nest.jsアプリ
- nest.jsの環境づくり
- node_modulesをvolumeマウント化
- postgresの環境づくり
nest.jsの環境づくり
まずは、nest.jsの環境を作っていこうと思います。先にNodeの環境を作成して、DevContainerでいきなりアクセスしてしまいます。
三つのファイルを作成します。
Dockerfile
ARG NODE_VER
FROM node:${NODE_VER} as base
RUN npm install -g npm@11.0.0
FROM base as dev
RUN npm i -g @nestjs/cli
USER node
WORKDIR /home/node/app
docker-compose.yml
version: "3.7"
services:
nest:
build:
args:
- NODE_VER=22.12.0
context: .
dockerfile: Dockerfile
target: dev
tty: true
volumes:
- type: bind
source: .
target: /home/node/app
.devcontainer/.devcontainer.json
{
"name": "procject-backend",
"dockerComposeFile": ["../docker-compose.yml"],
"service": "nest",
"workspaceFolder": "/home/node/app",
"customizations": {
"vscode": {
"extensions": [],
"settings": {}
}
},
"remoteUser": "node",
}
DevContainer内に入ったら、next.jsのプロジェクトを作成します。Dockerfile内でnest CLIをインストールしているので、実行可能かを試してみます。
nest --version
バージョンが帰ってきたら、成功しているのでそのままアプリを作っていきましょう。今回のアプリ名はnest-app
で作成していきます。
nest new nest-app
これで環境作成は完了です。
node_modulesをvolumeマウント化
node_modulesをvolumeマウントにすることで、コンテナ内に収めてしまいます。こちらの対応をしておくことで、元ファイル側のサイズを小さくすることができます。また、bindマウントしないことによりビルド速度を上昇させることができます。
こちらでやっていることは、「.dockerignoreでビルド時にnode_modulesをなかったことにして、Dockerfileでnode_modulesを作成してビルド、dokcer-compose.ymlでnode_modulesをボリュームマウントする」となります。Dockerファイルで作成している理由としては、dokcer-compose.ymlファイル経由で作成させるとroot権限で作成されて、詰まったいい思い出があります。
追加で、.dockerignore
ファイルを作成してください。
.dockerignore
nest-app/node_modules
Dockerfile
ARG NODE_VER
FROM node:${NODE_VER} as base
RUN npm install -g npm@11.0.0
FROM base as dev
RUN npm i -g @nestjs/cli
USER node
WORKDIR /home/node/app
RUN mkdir nest-app
COPY --chown=node:node nest-app nest-app
WORKDIR /home/node/app/nest-app
RUN mkdir node_modules
RUN chown node:node node_modules
RUN npm install
docker-compose.yml
version: "3.7"
services:
nest:
build:
args:
- NODE_VER=22.12.0
context: .
dockerfile: Dockerfile
target: dev
tty: true
volumes:
- type: bind
source: .
target: /home/node/app
- type: volume
source: node_modules
target: /home/node/app/nest-app/node_modules
volumes:
node_modules:
ファイルの適応が完了したら、**DevContainerを必ずRebuildしてください。**以上で、node_modulesのボリュームマウント化完了です。
next.jsのアプリを作成した際に発生したnpm installで持ってきたnode_modulesが元ファイルに残っていると思います。気になる方は、コンテナから抜け出して、お好きなように処理してください。
postgres環境づくり
postgresの環境は、16.6とバージョンを指定して作成していきます。公式のリファレンスを置いておきます。
環境変数を渡すので、まずは.envファイルを作成しておきます。本当のファイルの場合は、もっとちゃんとしたセキュリティにしてくださいね。
.env
POSTGRES_USER=user
POSTGRES_PASSWORD=password
docker-compose.yml
version: "3.7"
services:
nest:
build:
args:
- NODE_VER=22.12.0
context: .
dockerfile: Dockerfile
target: dev
tty: true
volumes:
- type: bind
source: .
target: /home/node/app
- type: volume
source: node_modules
target: /home/node/app/nest-app/node_modules
depends_on:
- postgresql
postgresql:
env_file: ".env"
container_name: postgresql
image: postgres:16.6
ports:
- 5432:5432
volumes:
- type: volume
source: postgres_data
target: /var/lib/postgresql/data
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
TZ: "Asia/Tokyo"
hostname: postgres
restart: always
volumes:
node_modules:
postgres_data:
nest.jsのアプリは、postgresの環境が立ち上がった後に立ち上がるように設定しておきます。あくまで開発環境なので、厳密である必要はないのですが、DB前提のシステムを組むと想定されるので念のためですね。
ここまでコピペできたら、**DevContainerを必ずRebuildしてください。**実行中のDevContainerからpostgresの環境にアクセスして以下のコマンドを実行してください。
psql -h postgres -U user
無事アクセスすることができれば、問題なく動作していると考えられます。
Prisma接続
Prismaのセットアップは公式のドキュメントが十分なので、今回作成したpostgresへアクセスするまでについて共有していきます。これから、Prsimaの勉強もしていくので、まとまったらブログ書きます。
npm install prisma --save-dev
npx prisma init # prismaセットアップ .envファイルが作成される
npm i --save @nestjs/config # nest.jsのコンフィグ読み込み用ライブラリ
nest-app/src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [ConfigModule.forRoot({isGlobal:true})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Globalで環境変数を読めるようにglobalで読み込んでおきます。これで、Prismaが作成した.envファイルも読み込むことができます。
スキーマファイルに定義を記入します。
nest-app/prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: <https://pris.ly/d/prisma-schema>
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: <https://pris.ly/cli/accelerate-init>
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
posts Post[]
}
model Post {
id Int @default(autoincrement()) @id
title String
content String?
published Boolean? @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
ここまでしてやっとで.env
ファイルの接続情報変更します。今回の環境では、以下に更新することで接続することができます。
DATABASE_URL="postgresql://user:password@postgres:5432/mydb?schema=public"
// DATABASE_URL="postgresql://{ユーザー}:{パスワード}@{ホスト名}:5432/mydb?schema=public"
以下のコマンドで先ほどコピペした内容がDBに反映されます。
npx prisma migrate dev --name init
コマンドが無事完了したら、以下のコマンドでprisma studioを立ち上げて反映できているか確認します。
npx prisma studio
かっこいい画面が立ち上がり、PostとUserが作成されていれば無事にアクセスできています。
おわり
今回の閑居構築で特に詰まった点としては、postgresの環境にアクセスできるまで長かったのでpostgresの環境作成が正しいのか試すことができなかった点ですね。postgresのイメージのドキュメントをちゃんと読みに行きましたね。今回は、DevContainerのVolumeを何度も消し飛ばして検証しました。開発体験としては、Git上でローカルのデータを管理しない想定なのでバインドはしたくありませんでした。PrismaのSeedなどを作りこんでおけば問題ないかと思います。
では2025年もよろしくお願いします。