データの置き場を選ぶ - volume / bind mount
volume は Docker が管理する永続領域、bind mount はホストの任意パスをそのまま見せる機能。UID/GID ズレや SELinux ラベルが原因で「書き込めない」エラーが起きがちなので、対処パターンを押さえる。
概念図
構文
docker run -v <name>:/path-in-container <image> # named volume
docker run -v /host/path:/path-in-container[:ro|:z|:Z] <image> # bind mount実例
名前付き volume を作って DB データを永続化
docker volume create pgdata
docker run -d --name db \
-v pgdata:/var/lib/postgresql/data \
postgres:16bind mount + 現在ユーザー UID + SELinux ラベル付与
docker run --rm \
-u "$(id -u):$(id -g)" \
-v "$PWD":/work:Z \
-w /work \
node:22 npm testvolume の立ち位置
Docker の volume は、コンテナのライフサイクルから独立した永続領域を Docker 自身が管理する仕組み。
実体は Linux では /var/lib/docker/volumes/<name>/_data に置かれ、Docker Desktop では VM 内に格納される。
ユーザーはホスト側の具体的なパスを意識せず、pgdata:/var/lib/postgresql/data のような名前でマウントするだけで良い。
docker volume ls や docker volume inspect で一覧・詳細を確認でき、バックアップは一時コンテナを立てて tar で吸い出すのが定番になる。
DB や Redis のデータのように「ホストのファイルシステムの構造に依存させたくない永続データ」は volume が第一選択になり、ホストユーザーの UID/GID 問題も起きにくい。
bind mount の UID/GID ズレ問題
bind mount はホストの任意のパスをそのままコンテナに見せるため、「開発中にソースコードを編集して即反映」といった用途に向いている。
ただしコンテナ内のプロセスが root(UID 0)や独自の非 root ユーザーで動いていると、作成されたファイルの所有者がホストのユーザーと合わず、「ホスト側で編集できない」「ビルドが upload 権限で失敗する」などの問題が起きる。
対策は docker run -u "$(id -u):$(id -g)" で現在のユーザー UID をコンテナに渡すか、Dockerfile で USER を指定してユーザーを固定するか、chown しておくか、の 3 通りが基本になる。
Windows 上の Docker Desktop では NTFS と Linux ファイルシステムの差で chmod が反映されない点もセットで覚えておく。
`:z` / `:Z` (SELinux) と `:ro`
RHEL / Fedora / Rocky Linux など SELinux が enforcing のディストリでは、bind mount 時にラベルが合わず「Permission denied」で弾かれることがある。
オプションの :z(小文字)は「このパスは複数コンテナで共有してよい」というラベルを付け、:Z(大文字)は「このコンテナ専用」のプライベートラベルを付ける。
ホスト側の共有ディレクトリに :Z を付けるとホスト上の他プロセスからアクセスできなくなる場合があるため、用途によって使い分ける。
読み取り専用マウントは :ro を末尾に付けるだけで、設定ファイルや SSL 証明書など「コンテナからは書き換えてほしくないデータ」に有効。
複数指定は :ro,Z のようにカンマで連結する。
# SELinux 有効ホストで共有ラベルを付与 / shared label under SELinux
docker run -v /srv/data:/data:z myimage
# コンテナ専用ラベル + 読み取り専用 / private label + read only
docker run -v /etc/ssl/certs:/certs:ro,Z myimage関連トピック
host.docker.internal- コンテナから「ホスト側の localhost」に繋ぎたいときに使う特殊名。Docker Desktop では最初から解決できるが、Linux では `--add-host=host.docker.internal:host-gateway` を付ける必要がある。 docker compose- 複数コンテナをまとめて起動・停止するための compose.yml。services / networks / volumes の 3 ブロックで構成され、`docker compose up -d` と `docker compose down` が中心操作になる。 