2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Prisma + Docker + PostgreSQLを使った効率的なデータベース

2
Posted at

はじめに

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 で外部キー制約を定義
  • createdAtupdatedAt フィールドで自動的にタイムスタンプを管理

マイグレーション管理

データモデルを変更する際は、マイグレーションを作成・実行する必要があります。

# 新しいマイグレーションを作成・適用
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コマンドは以下の処理を行います:

  1. 前回のマイグレーションからの変更を検出
  2. マイグレーションファイルを生成(prisma/migrations/[timestamp]_[name]
  3. マイグレーションをデータベースに適用
  4. 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.jsonprisma.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では、オートコンプリートと型チェックによって、実行前にエラーを防止できます。また、リレーションの扱いも直感的です。

開発ワークフロー

効率的な開発のために、以下のワークフローを推奨します:

  1. モデル定義: schema.prisma にデータモデルを定義/更新
  2. マイグレーション: prisma:migrate-dev で変更をデータベースに反映
  3. Client生成: マイグレーション時に自動で行われるが、必要に応じて prisma:generate を実行
  4. シードデータ: 開発/テスト用のデータを seed.ts で定義し、prisma:seed で投入
  5. アプリ開発: 生成されたPrisma Clientを使ってデータベース操作を実装
  6. モデル調整: 必要に応じてモデルを調整し、新しいマイグレーションを作成

データの可視化: 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

このコマンドは以下の処理を行います:

  1. データベースの全テーブルを削除
  2. すべてのマイグレーションを初めから順に再適用
  3. シードデータを投入

PostgreSQLへの直接アクセス

低レベルなSQLクエリを実行したい場合は、psqlスクリプトを使用します:

npm run psql

# PostgreSQLコンソール内で
SELECT * FROM users;
SELECT * FROM posts;

このコマンドは、Dockerコンテナ内のPostgreSQLに接続し、SQLコマンドを直接実行できるインタラクティブシェルを提供します。

まとめ

Prisma + Docker + PostgreSQLの組み合わせは、TypeScriptプロジェクトにおけるデータベース開発を大幅に効率化します。型安全なデータベースアクセス、マイグレーション管理、リレーションの簡潔な表現など、多くのメリットがあります。

今回紹介したスターターテンプレートと各スクリプトの使い方を理解することで、効率的なデータベース開発を始めることができます。特に、package.jsonに定義されたスクリプトは、よく使われる操作を簡単に実行できるようにしており、開発効率を大きく向上させます。

コードの全体像は、GitHub リポジトリで確認できます。

参考資料

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?