Skip to main content

第35章:ボリュームをComposeで定義する🧱

この章はひとことで言うと、**「DBの中身だけは絶対に消したくない」**を、Composeでちゃんと実現する回です😆💾 APIコンテナは作り直してOK。でもDBのデータは残したい。これ、個人開発でもチームでも超重要です🔥


この章のゴール🎯✨

  • Composeで 名前付きボリューム(named volume) を定義して使える🙂🧱
  • 「消える」「消えない」 の境界(downdown -v)が腹落ちする🧠💡
  • 「DBのデータが消えた😭」の典型事故を 先回りで回避できる🛡️🚑
  • 複数プロジェクトでも混乱しない ボリューム名の扱いがわかる🏷️🧹

1) ボリュームって結局なに?🤔🧱

ボリュームは「コンテナの外にある、消えにくいデータ置き場」です📦➡️🏠 コンテナは作り直せるけど、ボリュームに置いたデータは残る、ってイメージ💾✨

そしてComposeでは、ボリュームを「設計図に書いて」チーム/自分の環境で再現できるのが強い💪😄 (Composeファイルのデフォルト名は compose.yaml が推奨です📝)(Docker Documentation)


2) Composeのボリュームは「2か所に書く」🧩✍️

Composeで名前付きボリュームを使うときは、基本こう👇

  1. トップレベル(volumes:)で“名前”を定義する🧱
  2. サービス(例: DB)側の volumes: で“どこにマウントするか”を書く📎

この「二段構え」がわかると一気に安心します😌✨ (Composeのボリューム仕様はCompose Specification準拠が最新で、Docker DocsのCompose file referenceが基準です)(Docker Documentation)


3) まずは完成形:DBをボリュームで守るcompose.yaml🧱🐘✨

ここからはTodo API + Postgres想定でいきます😄 **ポイントは「Postgresのバージョンでマウント先が変わる」**ところ!これ、2025末〜で重要度が跳ね上がりました⚠️🧠

✅ おすすめ:PostgreSQL 18+(最新版寄り)での例🐘🆕

Postgres公式イメージは 18以上でデータディレクトリ周りが変更されています。18+ はボリュームのマウント先が /var/lib/postgresqlになります。(Docker Hub)

services:
api:
# ここは前章までの内容をそのまま想定(buildやportsなど)
# DB接続先は "db" を使うのが基本(同一Composeネットワーク)
environment:
DATABASE_HOST: db

db:
image: postgres:18
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: todo
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql # ✅ 18+ はこっち推奨

volumes:
db-data:

✅ もし PostgreSQL 17 以下を使うなら(古めの固定タグの場合)🐘⏳

17以下は、/var/lib/postgresql/data にマウントするのが重要です。 違う場所にマウントすると、コンテナ再作成時に「保存したはずなのに消えた😱」が起きます。(Docker Hub)

services:
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: todo
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data # ✅ 17以下はこっち

volumes:
db-data:

なぜこんなことが起きるの?🤔 Postgres公式イメージは「ここにデータ置くよ」って場所が決まっていて、そこにマウントしないと 匿名ボリューム(anonymous volume)が勝手に作られる → 次の再作成で再利用されず「あれ、データどこ?」になります😵‍💫 その注意喚起が公式に明記されています。(Docker Hub)


4) ハンズオン:本当に“消えない”ことを確認しよう🧪✅

Step 1:起動🚀

docker compose up -d

Step 2:ボリュームが作られたか確認👀🧱

docker volume ls

db-data って名前のボリュームが見当たらない…?」となったら、それはComposeがプロジェクト名を前に付けてる可能性が高いです(例:myproject_db-data)🏷️🙂 プロジェクト名は基本「そのcompose.yamlがあるディレクトリ名」になります。(Docker Documentation)

Step 3:DBに“印”をつける(データ作成)✍️🐘

まずpsqlで1行入れてみます(コマンドは例)🙂

docker compose exec db psql -U postgres -d todo -c "CREATE TABLE IF NOT EXISTS t (id int); INSERT INTO t (id) VALUES (1); SELECT * FROM t;"

Step 4:コンテナを消して、また起動🔁

ここが本番💪😆

docker compose down
docker compose up -d
docker compose exec db psql -U postgres -d todo -c "SELECT * FROM t;"

id = 1 が残ってたら勝ち🏆🎉 (docker compose downデフォルトではボリュームを消しません)(Docker Documentation)


5) いちばん大事:downdown -v の違い⚠️💥

docker compose down(安全寄り🛟)

  • コンテナ停止&削除
  • ネットワーク削除(など)
  • でもボリュームは基本残る🙂💾

「デフォルトで消えるもの」がDocker公式に整理されています。(Docker Documentation)

☠️ docker compose down -v(DB初期化スイッチ🔫)

  • Composeで定義した名前付きボリュームも消す
  • さらにコンテナに紐づく匿名ボリュームも消す

つまり DBがまっさら になります😇 -v/--volumes の説明が公式にあります。(Docker Documentation)

“初期化したいときだけ”使うのが鉄則です🧯😄


6) 「プロジェクト名」と「ボリューム名」問題🏷️🧠

6-1) なんで mydir_db-data みたいになるの?🤔

Composeは「プロジェクト名」で環境を分離します。 デフォルトは Composeファイルがあるディレクトリ名です。(Docker Documentation)

プロジェクト名は、たとえばこうやって変えられます👇

  • -p オプション
  • COMPOSE_PROJECT_NAME
  • Composeファイルのトップレベル name: など、優先順位も公式に書かれています。(Docker Documentation)

6-2) “ボリューム名を固定”したいとき(上級寄りだけど便利)🧱🔧

トップレベルボリュームに name: を付けると、実際のボリューム名を固定できます。 この name: は「プロジェクト名の接頭辞が付かない(その名前がそのまま使われる)」動きになります。(Docker Documentation)

volumes:
db-data:
name: todo-db-data

ただし固定名は「別プロジェクトと衝突」もしやすいので、チーム/用途が明確なときだけがおすすめ🙂⚠️


7) “外部ボリューム”という安全装置🛡️🧱

たとえば「このボリュームは絶対消したくない」「別のComposeからも使いたい」みたいなとき、external: true が使えます🙂

  • Composeは そのボリュームを作らない(既に存在する前提)
  • docker compose down でも external は消されない

どちらも公式に明記されています。(Docker Documentation)

例👇

volumes:
db-data:
external: true

externalにしたら、先に docker volume create db-data を作っておくイメージです🧰🙂


8) よくある事故🪤😵‍💫 → 即治しガイド🚑✨

事故1:DBデータが消えた😭

原因あるある:マウント先が違って、匿名ボリュームに逃げてた Postgres公式がまさにここを強めに注意しています。(Docker Hub)

✅ 対策

  • Postgres 18+:/var/lib/postgresql
  • Postgres 17-:/var/lib/postgresql/data をちゃんと使う🙂

事故2:うっかり down -v した😇

✅ 対策

  • 普段は down だけ
  • 初期化が必要なときだけ、意図して down -v

-v が何を消すかは公式に書いてあるので、“消える範囲”を固定で覚えよう🧠✨(Docker Documentation)


事故3:プロジェクト複製したらDBが別物になって混乱😵

原因:プロジェクト名が変わってボリューム名も変わった(例:A_db-dataB_db-data)🏷️

✅ 対策(どれか1つでOK)

  • -p でプロジェクト名を固定する
  • COMPOSE_PROJECT_NAME を固定する
  • Composeファイルに name: を書く

プロジェクト名の仕様と優先順位は公式にまとまってます。(Docker Documentation)


9) AIに手伝わせるプロンプト例🤖✨(コピペOK)

  • 「この compose.yaml のボリューム定義、データが消える可能性ある?危険ポイントを箇条書きで」🧯
  • docker compose downdown -v の違いを、初心者向けに超短く説明して」✂️
  • 「Postgresのタグが postgres:18 のとき、永続化のマウント先はどこが正しい?」🐘
  • 「“DB初期化したい時だけ安全にやる手順”を、事故らないチェックリストで作って」✅🧹

10) ミニ課題🎒✨(5〜10分)

  1. db-data をComposeで定義して起動できた?🚀
  2. テーブル1個作って down → up しても残る?💾
  3. わざと down -v して、データが消えるのを確認(※自己責任で!)😇
  4. docker volume ls で「どの名前で作られたか」を説明できる?🏷️🙂

次の章(第36章)では、複数サービスのログをまとめて見て運用するコツに入ります🪵📚✨ Composeを使うと“ログの見方”が一気に重要になるので、ここでボリュームを固めておくのはめちゃ良い順番です😄👍