第03章:事故る前に知る:マウントが「上書き」になる話🫠
この章はひとことで言うと… 「マウント=合体」じゃなくて、基本は“かぶせる(覆い隠す)” って感覚を作る章です🧠✨ これを知らないと、“昨日まで動いてたのに急に壊れた” が起きやすいです😇
3-1. まず結論:マウントすると「元の中身は見えなくなる」🫥
bind mount(ホストのフォルダをコンテナへ載せる)で、コンテナ側の既存フォルダにマウントすると そのフォルダに元から入ってたファイルは、マウント中は“隠れて”見えなくなります🫠 これが Docker 公式に明記されてます。(Docker Documentation)
しかも厄介なのが👇 「隠れてるだけ」だけど、コンテナの中から“取り外して元に戻す”みたいなことは基本できません(やるなら作り直し)💥(Docker Documentation)
3-2. 体験しよう:ファイルが“消えたように見える”ミニ実験🧪👀
やること:イメージの中に入ってたファイルが、bind mountで見えなくなるのを体験します。
Step A:デモ用イメージを作る📦
mkdir mount-accident-demo
cd mount-accident-demo
@'
FROM alpine:latest
RUN mkdir -p /app && echo "I am inside the IMAGE" > /app/in_image.txt
CMD ["sh", "-lc", "ls -la /app && echo '---' && cat /app/in_image.txt"]
'@ | Set-Content Dockerfile -Encoding UTF8
docker build -t mountdemo:1 .
Step B:マウントなしだと見える✅
docker run --rm mountdemo:1
期待:/app/in_image.txt が表示されます📄✨
Step C:空フォルダを /app に bind mount → “消える”😇
mkdir host-empty
docker run --rm --mount type=bind,source="$($PWD.Path)\host-empty",target=/app mountdemo:1
期待:/app が 空っぽ になります(=イメージ側の /app が隠れた)🫥
これが「マウントが上書き(に見える)」の正体です🫠 公式もこの挙動を “obscured(隠れる)” と説明してます。(Docker Documentation)
3-3. “volume”でも起きる?→ 起きる。でも挙動に差がある🧠
ここ、初心者が混乱しがちポイントです😂
-
bind mount:基本「覆い隠す」だけ(コンテナ側の元データは見えない)(Docker Documentation)
-
volume:
- すでに中身がある volumeをマウントすると、やっぱり覆い隠す🫥(Docker Documentation)
- でも、空の volume を “元からファイルがあるコンテナのディレクトリ” にマウントすると、初回だけ中身が volume 側にコピーされるのがデフォルトです📦➡️📦(Docker Documentation)
- コピーされたくないときは
volume-nocopyがあります🧷(Docker Documentation)
この「空 volume は最初にコピー」があるせいで、 “volume は隠れないっぽい?” みたいな誤解が起きます😇(実際は状況次第)
3-4. ありがちな事故シーン(TypeScript開発あるある)💥🧯
事故①:node_modules が“消えた”😱
よくある流れ👇
- イメージ作成時に
npm ciしてnode_modulesをコンテナに作った - 開発で
.:/appを bind mount - ホスト側の
./が/appを丸ごと覆う - 結果:コンテナ内の
node_modulesが見えず、Cannot find module ...祭り🎆
👉 対策の基本:
- 「アプリ本体」マウントと**「依存」**を分離する(依存は volume に逃がす)📦
- もしくはホスト側にも
node_modulesを用意する(ただしOS差や重さで地獄になりやすい😇)
事故②:dist/(ビルド成果物)が見えなくなって「あれ?」🤔
イメージ内で dist/ を作っても、.:/app で覆うと ホストに dist/ が無い限り見えないです🫥
→ つまり「ビルドしたのに動かない」って感じになります🫠
事故③:コンテナの重要フォルダを覆って即死💀
公式も“極端な例”として、/usr を bind mount で置き換えてコンテナが壊れる例を出してます😇(Docker Documentation)
(やる人ほぼいないけど、“重要な場所にマウントすると壊れる”感覚づくりに大事)
事故④:--mount だとホスト側のフォルダが無いとエラー📛
--mount type=bind は ホスト側パスが無いとエラーになります。(Docker Documentation)
一方 -v だと勝手にディレクトリ作って進むことがあり、空フォルダができて“隠れ事故”が発生しやすいです🫠(Docker Documentation)
👉 なのでこの教材では --mount を優先がおすすめです(事故が早く発覚する)👍(Docker Documentation)
3-5. 事故を防ぐ「3つの鉄則」📌✨
鉄則1:マウント先は“空の場所”にする🧺
- そのイメージに元から入ってる大事なファイルがある場所に、いきなり被せない🙅♂️
鉄則2:「依存」「生成物」「永続データ」を同じ場所に混ぜない🧃🍱
- 例:
/appに全部詰め込むと、マウントの1発で全部見えなくなりがち🫠 - 分けると、事故の影響範囲が小さくなります👍
鉄則3:マウント状態を“確認してから”悩む🔎 「ファイル消えた!」の前に、まずこれ👇
docker inspectで Mounts を見る(どこがどこにマウントされてるか)🧠(Docker Documentation)
3-6. デバッグ手順:「どこが隠れてる?」を即特定する🕵️♂️
手順1:コンテナを起動(名前つける)🏷️
docker run -d --name mountcheck --mount type=bind,source="$($PWD.Path)\host-empty",target=/app mountdemo:1 sh -lc "sleep 9999"
手順2:マウントの事実を確認🔍
docker inspect mountcheck --format "{{json .Mounts}}"
公式も docker inspect の Mounts を見ろって言ってます✅(Docker Documentation)
手順3:中身を確認👀
docker exec -it mountcheck sh -lc "ls -la /app"
手順4:片付け🧹
docker rm -f mountcheck
3-7. AIに聞くなら:最短で原因に当てるプロンプト例🤖✨
「現象」→「構成」→「ログ」の順で渡すと当たりやすいです🎯 (秘密系は貼らないでね🔒)
原因候補を3つ出させる👇
Dockerでbind mountしたら、コンテナ内のファイルが消えたように見えます。
以下のコマンド/構成から、原因候補を優先度順に3つと、確認コマンドを提案して。
- 実行コマンド:
docker run ...(ここに貼る)
- 期待: (こうなるはず)
- 実際: (こうなった)
“隠れてるだけか?”を判定させる👇
これは「マウントが既存の内容をobscureしている」パターンかどうか判定して。
判定に必要な docker inspect の見るべき項目も教えて。
3-8. まとめ:この章で持ち帰る感覚🧠🎁
- マウントは基本 “合体”じゃなくて“かぶせる” 🫥(Docker Documentation)
- かぶせた結果、元の中身は 見えなくなる(戻すなら作り直しが基本)😇(Docker Documentation)
- volume は 空なら初回コピーがある(ここが混乱ポイント)📦(Docker Documentation)
- 迷ったら
docker inspectの Mounts で事実確認🔎(Docker Documentation)
3-9. ミニ確認クイズ(1分)📝✨
- bind mount で
/appに載せたら、イメージ内の/appはどうなる?🫥 - 「空の volume」を「中身があるディレクトリ」にマウントすると、初回に起きやすいことは?📦
- “ファイル消えた!”とき、最初に見るべきコマンドは?🔎
次の第4章では、この事故を避けやすい形で Compose で “データ箱(named volume)” を定義していきます📦🧩 「node_modules を volume に逃がす」みたいな鉄板パターンも、そこで気持ちよく整理しようね😎✨