Skip to main content

第15章:マイグレーション&初期データ投入を自動化する🌱🧱

この章はひとことで言うと—— **「初回起動で、DBが勝手に“使える状態”になってる」**を作ります😎✨

  • マイグレーション(テーブル作成など)🧱
  • 初期データ投入(seed)🌱 この2つを、手で叩かない方向に寄せます✊

1) まず“設計の型”を頭に入れる🧠📌

✅ 目標(ここがゴール)🎯

  • いつでも「起動したらDB準備まで終わってる」🚀
  • しかも 手順が短い(初心者ほどここが命)🧡

✅ この章で採用する“安全寄り”の自動化方針🛡️

自動化には2ルートあります👇

  1. コマンドで一発(まずはこれ) 「必要な時だけ」マイグレ+seedを実行する(事故りにくい)🧯

  2. Compose起動時に“自動で一回だけ”走る(本章の本命) migrate という“一回で終わるサービス”を追加し、api の前に走らせる✨ ※ depends_oncondition: 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_oncondition が使えるから成立します✨ (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つだけ👇😺

  1. migratedb:setup を実行して 終わる
  2. migratedb が healthy になるまで 待つ🩺
  3. apimigrate成功したら起きる🌅 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 CopilotOpenAI Codex が使えるなら、seedは特に恩恵デカいです💥😆


まとめ🎉

  • まず docker compose run --rm ... で “一回だけ実行” を作る🧪 (Docker Documentation)
  • そのあと migrate サービスを作って、起動時に 自動で一回だけ 走らせる🚀 (Docker Documentation)
  • seed は 増殖しない設計(Upsert) にする🌱🛡️

次の章(キュー)に行く前に、ここまでできると「開発スタックっぽさ」が一気に出ますよ〜😎🔥