第15章:マイグレーション&初期データ投入を自動化する🌱🧱
この章はひとことで言うと—— **「初回起動で、DBが勝手に“使える状態”になってる」**を作ります😎✨
- マイグレーション(テーブル作成など)🧱
- 初期データ投入(seed)🌱 この2つを、手で叩かない方向に寄せます✊
1) まず“設計の型”を頭に入れる🧠📌
✅ 目標(ここがゴール)🎯
- いつでも「起動したらDB準備まで終わってる」🚀
- しかも 手順が短い(初心者ほどここが命)🧡
✅ この章で採用する“安全寄り”の自動化方針🛡️
自動化には2ルートあります👇
-
コマンドで一発(まずはこれ) 「必要な時だけ」マイグレ+seedを実行する(事故りにくい)🧯
-
Compose起動時に“自動で一回だけ”走る(本章の本命)
migrateという“一回で終わるサービス”を追加し、apiの前に走らせる✨ ※depends_onのcondition: service_completed_successfullyを使うのがコツです👍 (Docker Documentation)
2) まずは「手で叩ける」状態にする🧰✨(いきなり自動化しない)
自動化って、最初からやると壊れた時に詰みます😇 なので最初は ワンショット実行で「動く」ことを確認します。
2-1) スクリプトを用意する📜🛠️
例として、TypeScript ORMの Prisma で書きます(人気・定番ルート)😺 ただし考え方は他のORMでも同じ!
package.json(例)
{
"scripts": {
"db:migrate": "prisma migrate deploy",
"db:seed": "tsx prisma/seed.ts",
"db:setup": "npm run db:migrate && npm run db:seed"
}
}
migrate deployは「未適用のマイグレーションを適用する」用途で、非開発環境でも使われる想定のコマンドです🧱 (Prisma)- seed は Prismaの仕組み(
prisma db seed)を使ってもいいですが、**今はシンプルに“自分で seed.ts を実行”**でOKです(設定で沼りにくい)🌱 そもそも Prismaは統合されたseeding導線を用意しています🧩 (Prisma) tsxは seed 実行で相性が良いことが多いです(ESM/CJSの揉め事を避けやすい)🧯 (mseeeen.msen.jp)
Prisma 7系だと
prisma.config.tsを使う流れも強くなってます(package.json側の設定に警告が出るケースあり)📝 (Prisma) でもこの章では「seed.ts を直接叩く」方が迷子になりにくいので、まずはそっちで行きます🙆♂️
2-2) Compose経由で“1回だけ実行”してみる🎮
ここが超重要:ホストで叩かない(ランタイム固定の思想)🔒
docker compose run --rm api npm run db:setup
docker compose run --rmは「一回だけ実行して捨てる」用の定番です🧨(後に手順が短くなる) (Docker Documentation)- これで DBにテーブルができて、seedが入るなら勝ち🏆✨
3) 本命:Compose起動時に“自動で一回だけ”マイグレ&seedする🚀🌱
ここからが本章のメインディッシュ🍽️😋
3-1) 発想:migrate は「アプリじゃない」👀
api:ずっと動くサービスmigrate:やることやったら終了するサービス(ワンショット)✅
そして api はこう言うわけです👇
「
migrateが成功してから起きるね」😴➡️😎
これは Compose の depends_on の condition が使えるから成立します✨ (Docker Documentation)
3-2) compose.yaml(例:追加分だけ)
※ ここでは db の healthcheck も入れます(第14章の続きのイメージ)🩺
pg_isready で “DB起きた?” を見ます👀
services:
db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: app
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 3s
timeout: 3s
retries: 20
migrate:
build:
context: .
dockerfile: ./Dockerfile
command: ["npm", "run", "db:setup"]
depends_on:
db:
condition: service_healthy
api:
build:
context: .
dockerfile: ./Dockerfile
command: ["npm", "run", "dev"]
depends_on:
migrate:
condition: service_completed_successfully
db:
condition: service_healthy
ポイントは3つだけ👇😺
migrateはdb:setupを実行して 終わる✅migrateはdbが healthy になるまで 待つ🩺apiはmigrateが 成功したら起きる🌅service_completed_successfullyが効いてます✨ (Docker Documentation)
ちなみに Postgres の 18 系は 2025-09-25 にリリースされています🐘 (PostgreSQL)
(この教材が “2026最新前提” でも、古すぎない状態で書けます👍)
3-3) 起動して確認する🔍✨
docker compose up --build
見るべきログはこれ👇👀
migrateが走って ✅ で終わる- そのあと
apiが起動する
4) seed の地雷を踏まないコツ💣➡️🧯(超大事)
地雷①:seedが2回走るとデータが増殖する🐛📈
対策はどれかに寄せる👇
- Upsertする(推奨):同じキーなら更新 or スキップ
- INSERT … ON CONFLICT DO NOTHING 的な発想(DB側で防ぐ)🧱
- seed は「開発用ダミーデータ」だけに限定する(本番用の初期値とは分ける)🔐
seed.ts(Upsert例:雰囲気)
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
await prisma.user.upsert({
where: { email: "admin@example.com" },
update: { name: "Admin" },
create: { email: "admin@example.com", name: "Admin" },
});
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
地雷②:「起動のたびに migrate dev」みたいにすると事故る😇
- 開発用の
migrate devは便利だけど、起動フローに混ぜると “思わぬ挙動” が出やすいです🌀 - 起動時は deploy(適用) と seed(必要なら)に寄せるのが無難👍 (Prisma)
5) 便利コマンド集(困ったらここ)🧰✨
DBの準備だけやり直したい(migrateだけ)
docker compose run --rm migrate npm run db:migrate
seedだけ入れ直したい(seedだけ)
docker compose run --rm migrate npm run db:seed
🚨 全消しして作り直したい(最終手段)
Prismaだと migrate reset が代表例です(データ消えます)🔥 (fig.io)
※ 本番でやったら泣きます😭
6) AIを使うと爆速になるところ🤖⚡(使いどころ良い感じ)
- seed のダミーデータ案(ユーザー10人、投稿50件…)を作る📦✨
- “Upsert前提” の seed.ts を一瞬で叩き台生成🧠💨
- マイグレーションの「変更点まとめ」をレビューしてもらう👀📝
IDEで GitHub Copilot や OpenAI Codex が使えるなら、seedは特に恩恵デカいです💥😆
まとめ🎉
- まず
docker compose run --rm ...で “一回だけ実行” を作る🧪 (Docker Documentation) - そのあと
migrateサービスを作って、起動時に 自動で一回だけ 走らせる🚀 (Docker Documentation) - seed は 増殖しない設計(Upsert) にする🌱🛡️
次の章(キュー)に行く前に、ここまでできると「開発スタックっぽさ」が一気に出ますよ〜😎🔥