4.3 Dockerバインドマウント完全ガイド|ホストパスをコンテナに直接マウント

【第2章】イメージとコンテナの基本操作

Dockerバインドマウント完全ガイド|ホストパスをコンテナに直接マウント

4-2 では「Docker管理の外付けHDD」こと Named Volume を学びました。今回はもう一つの定番、Bind Mount(バインドマウント)。ホストOS上の任意のディレクトリをコンテナ内の好きな場所に繋ぐ仕組みです。

「いつものエディタでコードを書く → コンテナがそのコードで動く」という、開発者の日常ワークフローを支える主役です。

💡 この記事のゴール
① Bind Mount の仕組みと -v /host:/container の書式
② OS別(Linux / macOS / Windows)のパスの書き方
③ ハンズオン:nginx にホストのHTMLを差し込み、エディタ保存→ブラウザF5で即反映
④ 権限・:ro・性能の注意点
⑤ Named Volume(4-2)との使い分け判断軸

目次

  1. Bind Mount とは
  2. Named Volume との決定的な違い
  3. 書式と OS別のパス指定
  4. ハンズオン①:nginx でライブ編集
  5. ハンズオン②:設定ファイルを差し込む
  6. 権限と :ro の話
  7. Windows / macOS の性能と注意点
  8. よくあるつまずき
  9. 使い分けガイド
  10. まとめ

1. Bind Mount とは

Bind Mount は、ホスト側の特定ディレクトリ(またはファイル)を、コンテナ内の任意パスに「そのまま繋ぐ」マウント方式です。

【Bind Mount の模式図】
🖥️ ホスト(あなたのPC)
/home/you/project/src/
├── app.py
└── index.html
普段使うエディタで編集

📦 コンテナ内
/app/
├── app.py
└── index.html
アプリが参照

🔗 -v /home/you/project/src:/app
↑ ホストで保存 → コンテナから即見える(再起動不要)。逆方向も同じ。
💡 「コピー」ではなく「繋ぐ」
ホスト→コンテナにファイルがコピーされるわけではありません。同じ実体を両方から見る仕組みです(Linuxカーネルの mount システムコール)。だからリアルタイムに同期されます。

2. Named Volume との決定的な違い

観点 Named Volume(4-2) Bind Mount(4-3)
マウント元 Docker 管理領域(隠された場所) ホストの任意の絶対パス
-v の左辺 名前(例:mydata / で始まる絶対パス(例:/home/me/src
管理 Docker が責任を持つ ユーザが責任を持つ(普通のファイルシステム)
ホスト側から中身を編集 やりにくい(パスを意識しない前提) 普段のエディタでそのまま編集
向く用途 DB・本番永続データ 開発中のコード・設定ファイル注入
ポータビリティ 高(ホストOSを問わない) 低(環境ごとにパスが違う)
性能(Linux)
性能(Windows/macOS) △(VM境界のファイル共有、遅いことあり)

3. 書式と OS別のパス指定

3-1. 基本書式

docker run -v <ホストの絶対パス>:<コンテナ内のパス>[:ro|:rw] <image>

左辺が / で始まっていれば Docker は Bind Mount と判断します(/ で始まらなければ Named Volume)。

3-2. OS別のパスの書き方(カレントディレクトリの取り方)

環境 カレントディレクトリ展開
macOS / Linux (bash/zsh) $(pwd) docker run -v $(pwd):/app nginx
Windows PowerShell ${PWD} docker run -v ${PWD}:/app nginx
Windows cmd.exe %cd% docker run -v %cd%:/app nginx
WSL2 (bash) $(pwd) docker run -v $(pwd):/app nginx
⚠️ Windows のパスは変換が走る
C:\Users\me\src のようなパスは、Docker Desktop が自動で /c/Users/me/src 形式に変換します。うまく動かないときは "${PWD}" のようにダブルクォートで囲むと安全。
また WSL2 環境では、Linux側のパス(/home/me/src)をマウントしたほうが圧倒的に速いです。Windows側(/mnt/c/...)は遅い。

3-3. --mount 記法(より明示的)

# -v の代替として推奨される新記法
docker run --mount type=bind,source=/host/path,target=/container/path[,readonly] image

-v と機能は同じですが、key=value 形式で意図が明確。CI/CDスクリプトなどでは --mount のほうが可読性が高いです。


4. ハンズオン①:nginx でライブ編集

nginx 公式イメージでホスト側の HTML を配信し、エディタで保存したら即ブラウザに反映される流れを体験します。

4-1. 作業ディレクトリと HTML を準備

mkdir mysite
cd mysite

cat > index.html <<'EOF'
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Bind Mount Demo</title></head>
<body style="font-family:sans-serif;background:#fff3e0;padding:2em">
  <h1>🔗 Bind Mount テスト</h1>
  <p>ホスト側の変更が即コンテナに反映されるはず。</p>
</body></html>
EOF

4-2. bind mount で nginx 起動

docker run -d --name web -p 8080:80 \
  -v "$(pwd)":/usr/share/nginx/html:ro nginx

4-3. ブラウザで確認

http://localhost:8080 を開くと、こんな画面が出ます:



🔒 http://localhost:8080

🔗 Bind Mount テスト

ホスト側の変更が即コンテナに反映されるはず。

4-4. いつものエディタで編集 → F5

mysite/index.html を開いて <h1> の文言を変え、保存。ブラウザをリロード(F5)するだけで新しい内容が出ます。docker restart は不要。



🔒 http://localhost:8080

✏️ 編集後の新しい内容!

ホストで保存 → ブラウザでF5 → 即反映。Docker再起動不要。

✅ これが Bind Mount の価値
コンテナに入らず、Dockerを再起動せず、いつものエディタだけで作業が完結します。ソースコードの編集ループが爆速になる、開発の定番パターンです。

4-5. 後片付け

docker stop web
docker rm web
# ホスト側の mysite/ はそのまま残る(bind mount の元ファイルなので)

5. ハンズオン②:設定ファイルを差し込む

Bind Mount はファイル単位でもマウントできます。nginx の設定を自前のものに差し替える例:

# my-nginx.conf を用意(ごく単純な例)
cat > my-nginx.conf <<'EOF'
server {
    listen 80;
    location / {
        return 200 "Hello from my custom nginx config!\n";
        add_header Content-Type text/plain;
    }
}
EOF

# ファイル単位で bind mount(設定ファイルだけ上書き)
docker run -d --name web -p 8080:80 \
  -v "$(pwd)/my-nginx.conf":/etc/nginx/conf.d/default.conf:ro \
  nginx

# 動作確認
curl http://localhost:8080
# → Hello from my custom nginx config!
💡 ファイル単位マウントの便利さ
ディレクトリごと差し替えずに、設定ファイル1つだけをピンポイントで上書きできます。アプリの設定(application.yml.envmy.cnf 等)を開発・本番で切り替える時の定番手法です。

6. 権限と :ro の話

6-1. 読み取り専用でマウント

# :ro を付けると、コンテナからは読み取り専用
docker run -v "$(pwd)":/app:ro myapp

# --mount 記法なら readonly
docker run --mount type=bind,source="$(pwd)",target=/app,readonly myapp

コンテナ内のプロセスが万が一暴走しても、ホスト側のファイルを書き換えられないので安全策として有効です。設定ファイル・ソースコードなど「コンテナは見るだけでよい」ものは :ro 推奨。

6-2. UID/GID の落とし穴

# ホストで作ったファイルの所有者
$ ls -ln mysite/index.html
-rw-r--r-- 1 1000 1000 ...

# コンテナ内のユーザーが UID 1000 と一致していれば OK
# 違うと「Permission denied」の原因に
⚠️ Permission denied は UID/GID の不一致が原因のことが多い
コンテナ内のアプリが root で動いていれば大抵読めますが、公式イメージは非rootユーザーで動くものが増えています(nodepython の新しいタグ、postgres など)。この場合、ホスト側のファイル所有者とコンテナ内 UID が合わないと書き込みできません。docker run -u $(id -u):$(id -g) ... で揃えるのが回避策の1つ。Windows/macOS の Docker Desktop は内部で UID 変換してくれるので気にならないことが多い。

7. Windows / macOS の性能と注意点

Bind Mount は Linux では非常に速いですが、Windows と macOS では遅いことがあります

【Windows/macOS での bind mount はVM境界を越える】
📝 Windows NTFS
/ macOS APFS


ファイル共有
🖥️ Docker Desktop
の軽量Linux VM

📦 コンテナ
/app

↑ 毎回ファイルシステムを超えるので、大量のファイル読み書きが発生するワークロード(node_modules・.git・大量画像)で遅くなる

対策

  • WSL2 の Linux側に置く(Windows):/home/me/project 配下にコードを置いて、そこから起動すると劇的に速い
  • 不要ファイルを bind しないnode_modules/.git/ は named volume に逃がす、または .dockerignore 的な除外
  • cached / delegated モード(macOS):-v "$(pwd)":/app:cached などで整合性と引き換えに速度を得る(Docker Desktop 4.x 以降は VirtioFS がデフォルトで十分速い)

8. よくあるつまずき

症状 原因 対処
コンテナ内でファイルが空 相対パスを指定した → Docker が Named Volume と誤認 必ず絶対パス。bash なら $(pwd) で展開
Permission denied ホストとコンテナの UID 不一致 -u $(id -u):$(id -g) や chmod を見直し
Windowsでパスが不正と言われる バックスラッシュのまま渡している "${PWD}" か、Docker Desktop に変換してもらう
ホストで編集してもコンテナから見えない エディタが「一時ファイル→置換」方式で書いている(inodeが変わる) エディタの設定で atomic-save をOFF(vim/VSCode等)
性能が絶望的に遅い(macOS/Win) VM境界越え+ファイル数が多い WSL2側に配置、node_modules を named volume に
マウント先にあった既存ファイルが隠れた bind するとコンテナ側の元内容は上書き(見えなくなる) 仕様。bind 元に必要ファイルを揃えておく

9. 使い分けガイド

ケース おすすめ 理由
開発中のソースコードを反映 Bind Mount 普段のエディタで編集できる
カスタム設定ファイルを差し込む Bind Mount(ファイル単位) 環境ごとに設定を切り替えやすい
DBのデータファイル Named Volume ホスト側から触らない前提・性能良好
本番サーバの永続データ Named Volume(または外部ストレージ) バックアップ・権限管理が Docker で一元化
一時ファイル(機密・キャッシュ) tmpfs(4-4) ディスクに書かない
開発環境で「コード+DB」両方 両方を併用 コード=bind / データ=named の組み合わせが定番

実例として、典型的な「Webアプリ+DB」の開発構成では、こんな感じに両方を使い分けます:

# アプリ:ソースを bind mount で即反映
docker run -d --name app -p 3000:3000 \
  -v "$(pwd)/src":/app/src \
  myapp

# DB:named volume で安全に永続化
docker run -d --name db \
  -v pgdata:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

10. まとめ

押さえどころ 内容
書式 -v /host/絶対パス:/container/パス[:ro]
Named との判別 左辺が / 始まりなら bind、名前だけなら named
主な用途 開発中のソース共有・設定ファイル注入
OS注意 Windows/macOS は VM境界越えで遅いことあり、WSL2 Linux側推奨
権限 UID不一致で Permission denied、-u で揃える
安全策 :ro でコンテナから書き込み禁止
✅ 次のステップ
4-4 tmpfs マウントでは、3つ目のマウント方式「メモリ上の一時領域」を学びます。機密データ・一時キャッシュなどディスクに絶対書きたくないデータの受け皿です。

参考リンク


Dockerの基礎を動画で体系的に学びませんか?

実務で使う基礎だけを3時間に凝縮。環境構築から丁寧に解説しています。

Udemy Docker入門講座 クーポン割引で講座を見る →

コメント

タイトルとURLをコピーしました