運用中のDBに後付け Prisma Migrate を途中から導入する実践ガイド
運用中のDBに後付け Prisma Migrate を途中から導入する実践ガイド(ハマりどころ解説付き)
はじめに (きっかけ)
「このプロジェクト、最初は Prisma 使ってたけど、マイグレーションまでは管理してなかったんだよな...」
「開発も進んで、そろそろちゃんとスキーマ変更を管理したいけど、_prisma_migrations テーブルがない...」
そんな状況、ありませんか? 私もまさにその状況に直面しました。Prisma は導入済みでデータベーススキーマも存在しているけれど、Prisma Migrate によるマイグレーション管理は行われていない。運用が始まっているシステムだと、気軽に db push するわけにもいきません。
この記事では、そんな状況から Prisma Migrate を後付けで導入しようとして、実際に私が経験した試行錯誤やハマりどころを踏まえつつ、具体的な手順と注意点を解説します。
前提条件
この記事は、以下の状況を想定しています。
- Node.js と npm/yarn/pnpm がインストールされている。
- プロジェクトに Prisma CLI と Prisma Client が導入済み。(Prisma 3 以降を想定)
- マイグレーション管理されていない既存のデータベースとスキーマが存在する。
- 最終的に
prisma migrate devやprisma migrate deployを使ってスキーマ変更を管理したい。
準備: 超重要! schema.prisma の整備と配置場所
途中から Prisma Migrate を導入する上で、最も重要と言っても過言ではないのが、schema.prisma ファイルの準備とその配置場所です。
結論から言うと、schema.prisma はプロジェクトルート直下の prisma ディレクトリに配置してください。 これが Prisma の標準的な規約であり、後述する多くのトラブルを回避する鍵になります。
具体的な手順は以下の通りです。
-
prismaディレクトリの作成:
プロジェクトルートにprismaディレクトリがなければ作成します。mkdir prisma -
schema.prismaの移動:
もしschema.prismaがプロジェクトルートなど、prismaディレクトリ以外の場所にある場合は、prismaディレクトリの中に移動させます。# 例: ルートにある schema.prisma を移動する場合 mv schema.prisma prisma/ -
schema.prismaと DB スキーマの同期:
prisma/schema.prismaの内容を、現在のデータベーススキーマの構造と一致させる必要があります。これには主に2つの方法があります。-
prisma db pullを使う (推奨):
現在のデータベーススキーマを元にschema.prismaを自動生成(または上書き)します。これが最も簡単で確実です。npx prisma db pull注意: このコマンドは
prisma/schema.prismaをデータベースの内容で完全に上書きします。手動で追記したコメントやカスタム設定などがある場合は、実行前にバックアップを取るか、実行後に再度追記してください。 -
手動で編集する:
既存のprisma/schema.prismaを直接編集し、現在のデータベーススキーマと完全に一致するように修正します。テーブル定義、カラム定義、リレーションなどを正確に記述する必要があります。
-
これで、Prisma Migrate を導入する準備が整いました。prisma/schema.prisma が最新のDB状態を反映しているはずです。
導入方法: ベースラインの設定 (resolve --applied を使用)
Prisma 3 以降では、既存のデータベーススキーマを Prisma Migrate の管理下に置く(ベースラインを設定する)ために prisma migrate resolve コマンドを使用します。
(注記) Prisma 2.x 系には prisma migrate baseline という専用コマンドがありましたが、Prisma 3 以降では非推奨となり、resolve コマンドに機能が統合されました。
手順:
-
ベースライン用マイグレーションディレクトリ作成:
最初のマイグレーションファイル(実際には空のスキーマからの差分を記録するもの)を格納するディレクトリを作成します。名前は公式ドキュメントに合わせて0_initとするか、混乱を避けるためにタイムスタンプ付きの名前にしても良いでしょう(例:20250407000000_init)。ここでは0_initを使います。mkdir -p prisma/migrations/0_init -
(任意だが推奨) 空スキーマからの差分 SQL 生成 (記録用):
現在のschema.prismaの状態を表現する SQL を生成し、migration.sqlとして保存します。これは実際にデータベースに適用するためのものではなく、あくまで「この状態がベースラインである」という記録のためです。npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql注意: 必ず
--from-emptyを付け、--to-schema-datamodelで正しいprisma/schema.prismaのパスを指定してください。 -
マイグレーションを「適用済み」としてマーク:
作成した0_initマイグレーションが、あたかも既にデータベースに適用されたかのように Prisma に認識させるため、以下のコマンドを実行します。npx prisma migrate resolve --applied 0_initこれにより、
_prisma_migrationsテーブルが(なければ)作成され、0_initが適用済みとして記録されます。
これで、既存のデータベーススキーマが Prisma Migrate の管理下に置かれました。
ハマりどころとトラブルシューティング
さて、ここからは私が実際にハマった点や、その解決策について共有します。これらの多くは schema.prisma の配置場所が原因でした。
1. schema.prisma の場所が prisma/ ディレクトリじゃない場合
最初に試したとき、schema.prisma をプロジェクトルートに置いたまま進めようとして、以下の問題に遭遇しました。
-
prisma migrate diffでのエラー:
--to-schema-datamodel ./schema.prismaのように指定しても、Error: Could not load ... file or directory not foundというエラーが発生しました。これは Prisma CLI が規約通りprisma/schema.prismaを期待しているためと考えられます。prisma/ディレクトリに移動し、パスをprisma/schema.prismaに修正することで解決しました。 -
prisma migrate resolveでのP3017エラー:
schema.prismaをルートに置いたまま、--schema ./schema.prismaオプションを使ってresolveを試みたところ、以下のエラーが発生しました。$ npx prisma migrate resolve --schema ./schema.prisma --applied 0_init Environment variables loaded from .env Prisma schema loaded from schema.prisma # スキーマは読み込めているが... Datasource "db": PostgreSQL database "geake", schema "public" at "localhost:5432" Error: P3017 # ↓ エラー発生! The migration 0_init could not be found. ...--schemaオプションでスキーマファイルの場所は指定できているにも関わらず、resolveコマンドがprisma/migrations/0_initディレクトリを見つけられないという状況でした。原因の推測と結論: Prisma CLI は、たとえ
--schemaでスキーマの場所を指定されても、マイグレーションディレクトリの探索など、内部的な処理においてprisma/ディレクトリ構造という**「規約」**に強く依存している可能性が高いです。標準的でない場所にschema.prismaがあると、この規約から外れるため、0_initのようなマイグレーション名を正しく解決できないようです。
対策はただ一つ、schema.prismaはprisma/ディレクトリに置くしかないっぽい😇
2. prisma migrate resolve での P3017 エラー (再訪)
schema.prisma の場所が適切でも、P3017 エラーが出る可能性はあります。
-
マイグレーション名の指定ミス:
--appliedに指定する名前は、prisma/migrationsディレクトリ内に実際に存在するディレクトリ名と完全に一致させる必要があります。ls prisma/migrationsで確認し、0_initなのか、あるいは<timestamp>_<name>形式の名前なのかを正確に指定してください。# ls prisma/migrations で確認した名前を指定する npx prisma migrate resolve --applied <実際のディレクトリ名> -
0_initの扱い: 私の経験では、schema.prismaがprisma/ディレクトリにあれば、resolve --applied 0_initは問題なく動作しました。しかし、--schemaオプションを使った場合は失敗した経緯もあり、ツールの挙動がパスの状況によって変わる可能性は否定できません。規約に従うのが最も安全です。
導入後の確認
resolve コマンドが成功したら、以下の点を確認しましょう。
-
_prisma_migrationsテーブルの存在: データベース内にこのテーブルが作成されているか確認します。-- 例: PostgreSQL の場合 \dt _prisma_migrations; SELECT * FROM _prisma_migrations;-
prisma migrate statusコマンド: このコマンドで、Prisma がデータベースのマイグレーション状態をどのように認識しているか確認できます。ベースライン (0_initなど) が適用済み (Applied) になっていれば OK です。
npx prisma migrate status今後の運用
-
これで、Prisma Migrate の管理下にデータベースを置くことができました! 今後は以下のように運用できます。
-
スキーマ変更:
prisma/schema.prismaを編集します。 -
マイグレーション作成と開発 DB への適用:
npx prisma migrate dev --name <migration_description>を実行します。 -
本番環境などへの適用:
npx prisma migrate deployを実行します。
まとめ
運用中のシステムに後から Prisma Migrate を導入するのは、いくつかのポイントを押さえれば十分に可能です。
-
prisma migrate resolve --applied <baseline_migration_name>を使ってベースラインを設定するのが現在の標準的な方法です。 -
最重要:
schema.prismaは必ずprisma/ディレクトリに配置する! これだけで多くの問題を回避できます。 -
resolveコマンドで指定するマイグレーション名は、実際に存在するディレクトリ名と一致させる。 - ハマりどころを知っておけば、スムーズに導入を進められます。
この記事が、同じような状況で困っている方の助けになれば幸いです。
Discussion
resolveは上記に該当しないので、機能してないのかもしれないです🤔resolveのリファレンスには--schemaありますけど、、😅本当ですね・・・。
完全に罠と化してる状態かもです。
それか、0_initみたいなフォルダ名のときだけとか?なのかなって今更思ったりしました。