はじめに
Prisma、Docker、PostgreSQLを組み合わせた開発環境の構築方法と、効率的なデータベース開発のワークフローについてまとめました。
こちらのサンプルコードを使用しています。
Prismaとは
Prismaは、TypeScript/JavaScript向けの次世代ORMです。型安全なデータベースアクセス、自動生成されるクエリビルダー、マイグレーション管理などの機能を提供し、データベース操作を簡素化します。
開発環境のセットアップ
本記事では、Docker、Docker Compose、Prisma、PostgreSQLを使った開発環境を前提としています。リポジトリのクローンから開発環境の起動までの手順は以下の通りです。
# リポジトリのクローン
git clone https://github.com/ssssswooooo/prisma-docker-postgres-starter.git
cd prisma-docker-postgres-starter
# Dockerコンテナのビルドと起動
docker compose up -d --build
# Prisma Clientの生成
docker compose exec app npm run prisma:generate
# データベースマイグレーションの実行
docker compose exec app npm run prisma:migrate-dev -- --name init
# シードデータの投入
docker compose exec app npm run prisma:seed
プロジェクト構成
このスターターテンプレートは、以下のような構成になっています:
.
├── Dockerfile # アプリケーションコンテナの定義
├── compose.yaml # Dockerサービス設定
├── package.json # Node.js設定・依存関係
├── tsconfig.json # TypeScript設定
├── .dockerignore # Dockerビルド除外ファイル
├── .gitignore # Git除外ファイル
└── src/ # ソースコード
├── index.ts # アプリケーションエントリーポイント
└── prisma/ # Prisma関連ファイル
├── schema.prisma # データモデル定義
└── seed.ts # シードデータスクリプト
package.jsonのスクリプト説明
プロジェクトのpackage.jsonには、開発に便利な様々なスクリプトが定義されています。これらを理解することで、効率的な開発が可能になります:
"scripts": {
"build": "tsc", // TypeScriptのコンパイル
"start": "node dist/index.js", // コンパイル済みアプリの実行
"dev": "ts-node src/index.ts", // 開発モードでアプリを実行
// Prisma関連コマンド
"prisma:migrate-dev": "prisma migrate dev --schema ./src/prisma/schema.prisma", // 開発用マイグレーション作成と適用
"prisma:migrate-create": "prisma migrate create --schema ./src/prisma/schema.prisma", // マイグレーションファイルの作成のみ
"prisma:migrate-deploy": "prisma migrate deploy --schema ./src/prisma/schema.prisma", // 本番環境用マイグレーション適用
"prisma:db-pull": "prisma db pull --schema ./src/prisma/schema.prisma", // 既存DBからスキーマを生成
"prisma:db-push": "prisma db push --schema ./src/prisma/schema.prisma", // マイグレーションなしでスキーマを適用
"prisma:generate": "prisma generate --schema ./src/prisma/schema.prisma", // Prisma Clientの生成
"prisma:seed": "prisma db seed --schema ./src/prisma/schema.prisma", // シードデータの投入
"prisma:studio": "prisma studio --schema ./src/prisma/schema.prisma --hostname 0.0.0.0", // Prisma Studioの起動
"seed": "ts-node src/prisma/seed.ts", // シードスクリプトの直接実行
"psql": "docker exec -it prisma_docker_starter_db psql -U user -d mydatabase" // PostgreSQLへの直接アクセス
}
主要なスクリプトの用途:
- prisma:generate: スキーマから型付きのPrisma Clientを生成
- prisma:migrate-dev: 開発環境でのマイグレーション作成・適用
- prisma:migrate-deploy: 本番環境へのマイグレーション適用
- prisma:seed: テストデータの投入
- prisma:studio: データベース管理用GUIの起動
- psql: PostgreSQLに直接アクセスしてSQLを実行
データモデルの設計と実装
Prismaの大きな特徴は、schema.prismaファイルでデータモデルを宣言的に定義できることです。このプロジェクトでは、以下のようなシンプルなブログ系のデータモデルを定義しています:
model User {
id Int @id @default(autoincrement())
name String
email String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[]
@@map("users")
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
author User @relation(fields: [authorId], references: [id])
authorId Int
@@map("posts")
}
重要なポイント
-
@idや@defaultなどのアノテーションで、フィールドの制約や初期値を設定 -
@@map()でテーブル名をカスタマイズ(慣例的に複数形・小文字を使用) -
@relationで外部キー制約を定義 -
createdAt、updatedAtフィールドで自動的にタイムスタンプを管理
マイグレーション管理
データモデルを変更する際は、マイグレーションを作成・実行する必要があります。
# 新しいマイグレーションを作成・適用
docker compose exec app npm run prisma:migrate-dev -- --name add_new_field
# 本番環境へのマイグレーション適用(CIパイプライン等で使用)
docker compose exec app npm run prisma:migrate-deploy
prisma:migrate-devコマンドは以下の処理を行います:
- 前回のマイグレーションからの変更を検出
- マイグレーションファイルを生成(
prisma/migrations/[timestamp]_[name]) - マイグレーションをデータベースに適用
- Prisma Clientを自動的に再生成
マイグレーションは src/prisma/migrations ディレクトリに保存され、バージョン管理されます。これにより、チーム開発でのスキーマ変更の追跡や、本番環境への安全なデプロイが可能になります。
シードデータの作成
テスト・開発用のサンプルデータを簡単に投入できるのもPrismaの利点です。src/prisma/seed.ts ファイルに、以下のようなシードスクリプトを記述しています:
async function main() {
try {
// ユーザーデータのクリーンアップ(既存の場合)
await prisma.post.deleteMany({});
await prisma.user.deleteMany({});
console.log('既存データをクリーンアップしました');
// ユーザーの作成
const user1 = await prisma.user.create({
data: {
name: '山田太郎',
email: 'taro@example.com',
},
});
// 投稿の作成
const post1 = await prisma.post.create({
data: {
title: 'Prismaの使い方',
content: 'Prismaは次世代のORMで、TypeScriptとの相性が抜群です。',
published: true,
authorId: user1.id,
},
});
// ... その他のシードデータ
} catch (error) {
console.error('シードの実行中にエラーが発生しました:', error);
process.exit(1);
} finally {
// Prismaクライアントの切断
await prisma.$disconnect();
}
}
シードデータを実行するには、prisma:seedスクリプトを使用します:
docker compose exec app npm run prisma:seed
このコマンドはpackage.jsonのprisma.seed設定に基づいて、TypeScriptのシードスクリプトを実行します。
アプリケーションでのPrisma Client利用
実際のアプリケーションコードでは、Prisma Clientを使って型安全なデータベース操作を行います:
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// 基本的なCRUD操作
async function main() {
// 作成(Create)
const newUser = await prisma.user.create({
data: {
name: '新規ユーザー',
email: 'new@example.com',
},
});
// リレーションを含む作成
const userWithPost = await prisma.user.create({
data: {
name: 'ブロガー',
email: 'blogger@example.com',
posts: {
create: {
title: '最初の投稿',
content: '内容...',
published: true,
},
},
},
});
// 読み取り(Read)
const allUsers = await prisma.user.findMany();
// リレーションを含む読み取り
const usersWithPosts = await prisma.user.findMany({
include: {
posts: true,
},
});
// 条件付き検索
const publishedPosts = await prisma.post.findMany({
where: {
published: true,
},
});
// 更新(Update)
const updatedUser = await prisma.user.update({
where: { id: 1 },
data: { name: '更新後の名前' },
});
// 削除(Delete)
const deletedPost = await prisma.post.delete({
where: { id: 1 },
});
}
Prisma Clientでは、オートコンプリートと型チェックによって、実行前にエラーを防止できます。また、リレーションの扱いも直感的です。
開発ワークフロー
効率的な開発のために、以下のワークフローを推奨します:
-
モデル定義:
schema.prismaにデータモデルを定義/更新 -
マイグレーション:
prisma:migrate-devで変更をデータベースに反映 -
Client生成: マイグレーション時に自動で行われるが、必要に応じて
prisma:generateを実行 -
シードデータ: 開発/テスト用のデータを
seed.tsで定義し、prisma:seedで投入 - アプリ開発: 生成されたPrisma Clientを使ってデータベース操作を実装
- モデル調整: 必要に応じてモデルを調整し、新しいマイグレーションを作成
データの可視化: Prisma Studio
Prisma Studioは、データベースの内容を視覚的に確認・編集できるGUIツールです。
docker compose exec app npm run prisma:studio
このコマンドは、Prisma Studioをコンテナ内で起動し、外部からアクセスできるようにします。
ブラウザで http://localhost:5555 にアクセスすると、以下のことができます:
- テーブル内のデータ閲覧・編集
- リレーションの確認
- レコードの追加・削除
これは特にデータ構造の確認やテストデータの調整に便利です。
トラブルシューティング
データベースリセット
開発中にデータベースをリセットする必要がある場合は:
docker compose exec app npx prisma migrate reset --force --schema ./src/prisma/schema.prisma
このコマンドは以下の処理を行います:
- データベースの全テーブルを削除
- すべてのマイグレーションを初めから順に再適用
- シードデータを投入
PostgreSQLへの直接アクセス
低レベルなSQLクエリを実行したい場合は、psqlスクリプトを使用します:
npm run psql
# PostgreSQLコンソール内で
SELECT * FROM users;
SELECT * FROM posts;
このコマンドは、Dockerコンテナ内のPostgreSQLに接続し、SQLコマンドを直接実行できるインタラクティブシェルを提供します。
まとめ
Prisma + Docker + PostgreSQLの組み合わせは、TypeScriptプロジェクトにおけるデータベース開発を大幅に効率化します。型安全なデータベースアクセス、マイグレーション管理、リレーションの簡潔な表現など、多くのメリットがあります。
今回紹介したスターターテンプレートと各スクリプトの使い方を理解することで、効率的なデータベース開発を始めることができます。特に、package.jsonに定義されたスクリプトは、よく使われる操作を簡単に実行できるようにしており、開発効率を大きく向上させます。
コードの全体像は、GitHub リポジトリで確認できます。