【Docker】volume完全ガイド|内部構造・5種マウント・driver_opts・バックアップ7パターン・ホスト間移行・UID問題

Docker

Dockerコンテナはデフォルトで書き込みレイヤーが使い捨て——docker rmした瞬間にDBも、ユーザーがアップしたファイルも、ログも消えます。この壁を越えるための核心機能がvolume(ボリューム)。MySQL/PostgreSQLのデータ、WordPressの画像、Redisのスナップショット、Prometheusの時系列データ——本番・開発を問わず「永続化すべきもの」は全てvolumeに載せる、というのが2026年の標準です。

入門記事の多くは-v db_data:/var/lib/mysqlの例で止まっていますが、実運用で差がつくのはvolume driverによるクラウドストレージ連携(AWS EBS/Azure Files)、backup/restore戦略、ホスト間移行、権限問題(UID/GID)、read-only/shared propagation、labelsによるライフサイクル管理、prune –filterなどの運用寄りトピック。これらを知らないとDBのフルバックアップや本番移行で必ず困ります。

この記事では、volumeの内部構造/var/lib/docker/volumes/)から始めて、5種のマウントタイプ比較、driver_opts(NFS/cifs/tmpfs/sshfs)、バックアップ/リストア7パターンホスト間移行、権限/labels/prune の運用テクニック、macOS・Windows特有の性能問題まで、volumeを使いこなすための完全ガイドとしてまとめます。bind mountとの使い分け詳細は【Docker】bind mountとvolumeの違いと使い分け、Compose基礎は【Docker】Compose完全ガイドで補完できます。

この記事で学べること

  • volumeの内部構造/var/lib/docker/volumes/の中身)
  • 5種のマウント比較:named/anonymous/bind/tmpfs/npipe
  • volume driver活用(local/NFS/cifs/sshfs/AWS EBS/Azure Files)
  • driver_optsmount typeやsize制限を細かく指定
  • Composeのexternallabelsnamedriver_optsで運用管理
  • backup/restore 7パターン(tar/helper container/Compose連携)
  • ホスト間移行:docker run --rm+tar + scpの実戦テクニック
  • UID/GID問題(Linuxでの所有者ズレ)と解決策
  • ro:z:Z(SELinux)/propagationの適用
  • labels+prune --filter誤削除事故を防ぐ
  • macOS/Windowsでの性能問題と回避策
  • disaster recovery:volume消失時の復旧手順
スポンサーリンク

30秒クイックスタート:volume操作の4大コマンド

基本操作
# ① 作成(明示的に名前を付ける)
docker volume create db_data

# ② マウントして使う
docker run -d --name mydb \
  -e MARIADB_ROOT_PASSWORD=root \
  -v db_data:/var/lib/mysql \
  mariadb:11

# ③ 一覧・詳細確認
docker volume ls
docker volume inspect db_data

# ④ 削除(コンテナ停止後)
docker volume rm db_data
新構文(–mount、推奨)
# -v より明示的で安全な --mount 構文
docker run -d --name mydb \
  -e MARIADB_ROOT_PASSWORD=root \
  --mount type=volume,source=db_data,target=/var/lib/mysql \
  mariadb:11

# bind mountと区別しやすい
docker run --mount type=bind,source=./conf,target=/etc/conf ...
docker run --mount type=tmpfs,target=/tmp ...

2026年は--mount構文を推奨-v db_data:/pathは「volumeなのか./db_data:/path(bind mount)なのか」が書いた場所の先頭パスでしか判別できず、事故が起きやすい。--mount type=volume,source=...なら意図が明示され、tmpfsやNFS driverも同じ構文で扱えます。

volumeの内部構造:/var/lib/docker/volumes/

Dockerのnamed volumeはホスト上の決まった場所に作られ、Dockerエンジンが管理します。これを知っていると障害時のデータ救出や移行が楽になります。

ホスト側の実体確認
# Docker用ディレクトリ(Linuxの既定)
ls -la /var/lib/docker/volumes/

# 特定volumeの中身を見る(要sudo)
sudo ls -la /var/lib/docker/volumes/db_data/_data/
# → ibdata1  ib_logfile0  mysql/  performance_schema/ ...

# ボリュームの物理パスを確認
docker volume inspect db_data
# [
#   {
#     "CreatedAt": "2026-04-22T10:00:00+09:00",
#     "Driver": "local",
#     "Labels": null,
#     "Mountpoint": "/var/lib/docker/volumes/db_data/_data",
#     "Name": "db_data",
#     "Options": null,
#     "Scope": "local"
#   }
# ]

macOS/Windows(Docker Desktop)の場合:volumeはホストOSではなくLinuxVM内(Hyper-V/WSL2/HyperKit)に作られます。そのため/var/lib/docker/volumes/をFinder/Explorerで開けません。中身を見るにはdocker run --rm -v db_data:/data alpine ls /dataのように一時コンテナ経由でアクセスするのが基本。

匿名volume(anonymous volume)

anonymous volumeの例と落とし穴
# Dockerfileの VOLUME 宣言やimage定義で自動作成される
FROM mariadb:11
VOLUME /var/lib/mysql

# 明示指定なしで起動すると勝手に匿名volumeが作られる
docker run -d mariadb:11       # → 無名volumeが作られてデータが入る
docker stop <cid>
docker rm <cid>
# → 匿名volumeは残るが「どれがどのコンテナのだったか」不明

# 一覧で名前がハッシュ値のがそれ
docker volume ls
# DRIVER    VOLUME NAME
# local     3f8d2a1c9b4e5f6a7b8c...   ← 匿名volume

匿名volumeはゴミが溜まりがち。「誰が作ったか分からない」状態で残り続けDisk Fullを招くので、必ず明示的にnamed volumeで運用しましょう。定期的にdocker volume ls -qf dangling=trueで孤児volumeを洗い出し、docker volume pruneで掃除を。

マウントタイプ5種の完全比較

種類 実体 永続化 用途
named volume Docker管理領域+命名 ◎(明示削除まで) DB/uploads/本番データ全般
anonymous volume Docker管理領域+自動命名 △(管理困難) 非推奨(ゴミが溜まりやすい)
bind mount ホストの任意ディレクトリ ソースコード/設定ファイル
tmpfs メモリ上の一時領域 ✗(再起動で消滅) 秘密鍵展開/セッション/高速一時IO
npipe Windows名前付きパイプ Windowsコンテナ内プロセス間通信
それぞれのマウント例
# named volume
docker run --mount type=volume,source=db_data,target=/var/lib/mysql ...

# bind mount
docker run --mount type=bind,source="$(pwd)/conf",target=/etc/conf,readonly ...

# tmpfs(メモリ、コンテナ終了で消える)
docker run --mount type=tmpfs,target=/tmp,tmpfs-size=100m ...

# read-only volume
docker run --mount type=volume,source=config,target=/etc/app,readonly ...

どれを選ぶか

  • DB/永続データ:named volume(第一選択
  • ソース/nginx.conf等:bind mount
  • 一時I/O/秘密展開:tmpfs
  • 複数ホスト共有:NFS driver付きvolume
  • クラウド運用:EBS/Azure Files driver

volume CLI操作完全リファレンス

主要コマンド
# 作成(labels/driver_optsで高度化)
docker volume create db_data
docker volume create \
  --label env=production \
  --label app=myapp \
  db_data_prod

# 一覧+フィルタ
docker volume ls
docker volume ls --filter "label=env=production"
docker volume ls --filter "name=db_"
docker volume ls -qf dangling=true        # 孤児(未使用)のみ

# 詳細(Mountpoint/Options/Labels)
docker volume inspect db_data

# 削除
docker volume rm db_data
docker volume rm $(docker volume ls -qf dangling=true)    # 孤児一括削除

# 未使用volume一括削除(prune)
docker volume prune

# 2026年推奨:labelsでフィルタして誤削除防止
docker volume prune --filter "label!=keep=true"

volumeの中身を覗く(ホストから直接触らない)

一時コンテナ経由でアクセス
# 既存volumeの中身を一覧
docker run --rm -v db_data:/data alpine ls -la /data

# 特定ファイルをcat
docker run --rm -v db_data:/data alpine cat /data/server.cnf

# volumeにファイルを投入
docker run --rm -v db_data:/data -v "$(pwd):/src" \
  alpine cp /src/myfile /data/

# volume内をシェルで触りたい
docker run --rm -it -v db_data:/data alpine sh

/var/lib/docker/volumes/配下を直接virmするのは非推奨。ファイル所有者/SELinuxコンテキスト/Dockerの管理情報と不整合が起きる可能性。必ず一時コンテナ経由docker run --rm -v ...)か専用コンテナ内から操作しましょう。

Composeでのvolume定義完全版

Composeのvolumeパターン全種
services:
  db:
    image: mariadb:11
    volumes:
      # ① named volume(top-levelで定義)
      - db_data:/var/lib/mysql

      # ② bind mount(相対パス)
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro

      # ③ --mount形式(明示的で推奨)
      - type: volume
        source: db_backup
        target: /backup
        volume:
          nocopy: true         # 既存volume内容を優先

      # ④ tmpfs(メモリ)
      - type: tmpfs
        target: /tmp/cache
        tmpfs:
          size: 104857600      # 100MB

      # ⑤ read-only bind mount
      - type: bind
        source: ./conf
        target: /etc/conf
        read_only: true

volumes:
  # 基本定義
  db_data:

  # ラベル付与(クリーンアップ時の保護に有用)
  db_backup:
    labels:
      env: "production"
      app: "myapp"
      keep: "true"

  # 外部で事前作成したvolumeを使う
  shared_data:
    external: true
    name: legacy_shared_data   # 既存名前指定

    # driver_optsでNFS等の高度マウント
  nfs_data:
    driver: local
    driver_opts:
      type: nfs
      o: "addr=10.0.0.100,rw,nfsvers=4"
      device: ":/export/data"

Compose関連のvolumeオプション

  • external: true:Compose外で作成済みのvolumeを参照(事故で消えない)
  • name: "xxx":自動プレフィックス(プロジェクト名)を付けずに固定名
  • labels::運用メタデータ。prune --filterで誤削除防止
  • driver:driver_opts::ローカル以外のストレージ
  • nocopy: true:既存volume内容を上書きしない(初回マウント制御)

volume driver:ローカル以外のストレージ連携

NFS(ネットワーク共有)

NFS driver_opts
volumes:
  shared:
    driver: local
    driver_opts:
      type: nfs
      o: "addr=192.168.1.100,rw,nfsvers=4"
      device: ":/exports/docker"

# mount(8)コマンドの互換性
# type / o / device が mount の -t / -o / &lt;src&gt; に対応

cifs/samba(Windows共有)

cifs設定
volumes:
  winshare:
    driver: local
    driver_opts:
      type: cifs
      o: "username=user,password=pass,uid=1000,gid=1000"
      device: "//192.168.1.50/share"

AWS EBS/Azure Files(クラウドストレージ)

プラグインインストール+利用
# REX-Ray (legacy) や Docker公式 CSI pluginを使用
# Kubernetesへ移行するなら各CSIドライバを推奨

# 例: AWS EBSプラグイン
docker plugin install rexray/ebs REXRAY_PREEMPT=true \
  EBS_ACCESSKEY=... EBS_SECRETKEY=...

docker volume create --driver rexray/ebs \
  --opt size=10 \
  --opt volumetype=gp3 \
  ebs_data

クラウド統合は2026年ではKubernetes CSIが主流

単発DockerホストでAWS EBS/Azure Diskを直接マウントする需要は減少し、Kubernetes+CSIドライバでの運用が一般的になりました。Dockerのdriver_optsで間に合う規模(単一ホスト、NFS程度)なら今でも便利ですが、複数ホスト/可用性が必要ならKubernetesへの移行を検討してください。

tmpfs driver(メモリ上の永続化風)

tmpfs volume
services:
  app:
    volumes:
      - type: tmpfs
        target: /app/cache
        tmpfs:
          size: 256M
          mode: 0755

# メモリ上なので超高速、コンテナ再起動で消える
# 秘密鍵の一時展開、セッションデータ等に最適

backup/restore:volumeデータを守る7パターン

volumeは永続化が目的ですが、それ自体が消える(プルーンミス/ホスト障害/人為ミス)可能性があります。日次バックアップの組み込みが実運用の前提。

①tar を使ったシンプルバックアップ(万能パターン)

backup.sh
#!/usr/bin/env bash
# volumeをtar.gzに固める
set -euo pipefail

VOLUME="db_data"
OUT="./backup/${VOLUME}_$(date +%Y%m%d_%H%M).tar.gz"
mkdir -p ./backup

docker run --rm \
  -v "$VOLUME":/data:ro \
  -v "$(pwd)/backup":/backup \
  alpine tar czf "/backup/$(basename $OUT)" -C /data .

echo "Backup: $OUT"

# 7日以上前の削除
find ./backup -name "*.tar.gz" -mtime +7 -delete

②tarによるrestore

restore.sh
#!/usr/bin/env bash
set -euo pipefail

VOLUME="db_data"
ARCHIVE="$1"

# 新規volumeを作成
docker volume create "$VOLUME"

# アーカイブを展開
docker run --rm \
  -v "$VOLUME":/data \
  -v "$(pwd)/$(dirname $ARCHIVE)":/backup:ro \
  alpine tar xzf "/backup/$(basename $ARCHIVE)" -C /data

echo "Restored: $ARCHIVE → $VOLUME"

③MySQL/MariaDB専用のmysqldump方式

アプリレベルダンプ(推奨)
# volumeレベルのtarよりDBレベルのdumpが安全
# → 整合性チェック済み/クロスバージョン対応
docker compose exec db mysqldump \
  --single-transaction \
  --routines --triggers --events \
  -u root -proot mydb | gzip > backup_$(date +%Y%m%d).sql.gz

# リストア
gunzip -c backup_20260422.sql.gz | \
  docker compose exec -T db mysql -u root -proot mydb

④PostgreSQL専用のpg_dump方式

pg_dump/pg_restore
# バックアップ(カスタム形式、高速並列リストア可)
docker compose exec postgres pg_dump -U app -F c -b -f /tmp/backup.dump mydb
docker compose cp postgres:/tmp/backup.dump ./backup_$(date +%Y%m%d).dump

# リストア
docker compose cp ./backup.dump postgres:/tmp/
docker compose exec postgres pg_restore -U app -d mydb -j 4 /tmp/backup.dump

⑤Docker Compose含みのフルバックアップ

全volume一括
#!/usr/bin/env bash
# 全volumeを個別tarに
set -euo pipefail

BACKUP_DIR="./backup/$(date +%Y%m%d_%H%M)"
mkdir -p "$BACKUP_DIR"

for vol in $(docker compose config --volumes); do
  FULL_NAME="$(basename $(pwd))_${vol}"
  docker run --rm \
    -v "$FULL_NAME":/data:ro \
    -v "$(pwd)/$BACKUP_DIR":/backup \
    alpine tar czf "/backup/${vol}.tar.gz" -C /data .
  echo "✓ $vol → ${vol}.tar.gz"
done

# compose.yml, .env 等もコピーして完全復元できるように
cp compose.yml .env "$BACKUP_DIR/"

echo "Full backup: $BACKUP_DIR"

⑥バックアップ専用volumeへdockerコンテナからtar出力

定期ジョブ向けhelperコンテナ
services:
  db:
    image: mariadb:11
    volumes:
      - db_data:/var/lib/mysql

  backup:
    image: alpine:latest
    profiles: ["backup"]
    volumes:
      - db_data:/data:ro
      - ./backup:/backup
    command: |
      sh -c "tar czf /backup/db_$(date +%Y%m%d).tar.gz -C /data ."

# 実行
# docker compose --profile backup run --rm backup

⑦AWS S3への自動アップロード

cronでS3へ
#!/usr/bin/env bash
# backup-to-s3.sh
set -euo pipefail

STAMP=$(date +%Y%m%d_%H%M)
LOCAL="./backup/db_${STAMP}.tar.gz"
S3_PATH="s3://mycompany-backup/docker-volumes/db_${STAMP}.tar.gz"

mkdir -p ./backup
docker run --rm \
  -v db_data:/data:ro \
  -v "$(pwd)/backup":/backup \
  alpine tar czf "/backup/db_${STAMP}.tar.gz" -C /data .

aws s3 cp "$LOCAL" "$S3_PATH" --storage-class STANDARD_IA

# 過去30日分は自動で消す(S3ライフサイクルポリシーでも可)
aws s3 ls s3://mycompany-backup/docker-volumes/ | \
  awk '$1 &lt; "'$(date -d "30 days ago" "+%Y-%m-%d")'" {print $4}' | \
  xargs -I{} aws s3 rm "s3://mycompany-backup/docker-volumes/{}"

推奨の組み合わせ:①開発環境:パターン①(tar)+profilesのhelperコンテナ、②本番DB:アプリレベル(③mysqldump/④pg_dump)+S3アップロード(⑦)、③crontabで日次3時、S3ライフサイクルで30日保持。GitHub Actionsでのスケジュール実行も可:【GitHub】Actions完全ガイドのscheduleセクション参照。

ホスト間移行:本番↔ステージング間でvolumeを移動

scp経由の移行フロー
# ソース側ホストで
docker run --rm \
  -v db_data:/data:ro \
  alpine tar czf - -C /data . \
  | ssh user@destination "cat &gt; /tmp/db_data.tar.gz"

# デスティネーション側ホストで
docker volume create db_data

docker run --rm \
  -v db_data:/data \
  -v /tmp/db_data.tar.gz:/backup/db_data.tar.gz:ro \
  alpine tar xzf /backup/db_data.tar.gz -C /data

# 中間ファイル削除
ssh user@destination "rm /tmp/db_data.tar.gz"
パイプで一発(中間ファイル無し)
# tar→ssh→tarの直結パイプライン
docker run --rm -v db_data:/data:ro alpine tar czf - -C /data . | \
  ssh user@destination \
  "docker run --rm -i -v db_data_new:/data alpine tar xzf - -C /data"

# 事前にデスティネーション側で
# docker volume create db_data_new を実行しておくこと

DBのvolumeを稼働中コンテナからcopyするとデータ不整合を起こします。移行前に必ずdocker compose stop dbか、アプリレベルダンプ(mysqldump/pg_dump)を使ってください。稼働中のInnoDBをtarで固めると起動時にCorrupt pageエラーが頻発します。

権限問題(UID/GID)とその解決

volumeの中のファイル所有者はコンテナ内プロセスのUIDが記録されます。ホストから見ると「知らないUID」になり、bind mount併用時やvolume中身を直接触る時にPermission deniedが頻発する典型的トラブルです。

UID/GIDの確認と調整
# volume内ファイルの所有者確認
docker run --rm -v db_data:/data alpine ls -la /data
# drwxr-xr-x 1 999 999 ...     ← UID 999 = mysql / mariadb

# コンテナ内プロセスのUID確認
docker compose exec db id
# uid=999(mysql) gid=999(mysql) groups=999(mysql)

# ホストユーザーと合わせたい場合
docker run --rm \
  --user "$(id -u):$(id -g)" \
  -v mydata:/data alpine touch /data/test

# Composeでuser指定
services:
  app:
    user: "1000:1000"      # ホストと合わせる

既存volumeの所有者を一括変更

chownで修正
# 間違えた所有者を全ファイル変更
docker run --rm -v db_data:/data alpine chown -R 999:999 /data

PUID/PGIDパターン(LinuxServer.io流)

LinuxServer.io系のイメージはPUIDPGID環境変数でプロセスUIDを実行時に変更できる設計。ホストのUIDを指定するとbind mount時の権限問題がゼロに。自作イメージでもentrypointスクリプトでusermodするパターンを採用すると便利です。

read-only/SELinux/propagationオプション

主要なマウントオプション
# 読み取り専用
docker run -v config_vol:/etc/app:ro ...
# --mount 構文
docker run --mount type=volume,source=config_vol,target=/etc/app,readonly ...

# SELinux共有ラベル(Fedora/RHEL/CentOS)
docker run -v db_data:/var/lib/mysql:z ...   # 共有
docker run -v db_data:/var/lib/mysql:Z ...   # プライベート
# z/Zを付けないとSELinux環境で Permission denied

# bind mountのpropagation(ホスト/コンテナ間での伝播)
docker run --mount type=bind,source=/host,target=/container,bind-propagation=rslave ...
# private / rprivate / shared / rshared / slave / rslave

# consistent / cached / delegated (macOS/Windows向き高速化)
docker run -v "$(pwd)":/app:delegated ...    # macOSで大規模fs高速化

macOS/Windowsでbind mountが遅い時:delegatedまたは:cachedを付けると劇的に速くなります。:delegatedは「コンテナ側の変更が優先」、:cachedは「ホスト側の変更が優先」というconsistency制御です。named volumeの場合はもともと高速なのでこれらのオプションは不要。

クリーンアップ戦略:labelsで事故を防ぐ

docker volume pruneコンテナから参照されていないvolumeを全削除します。稼働していないバックアップ用volumeや、一時的にstopしているコンテナのvolumeも対象になり得るため誤削除の事故が多発します。labels+filterで安全に運用しましょう。

安全なクリーンアップ
# ❌ 危険:全孤児を削除
docker volume prune

# ⭕ 安全:keepラベル付きは除外
docker volume prune --filter "label!=keep=true"

# ⭕ より安全:特定ラベルのみ削除対象
docker volume prune --filter "label=ephemeral=true"

# ⭕ 確認プロンプトなしで実行(CI向け)
docker volume prune -f --filter "label=ephemeral=true"
labels運用パターン
# 作成時にラベル付与
docker volume create \
  --label env=production \
  --label keep=true \
  --label app=myapp \
  db_data_prod

# Composeでラベル
volumes:
  db_data:
    labels:
      env: "production"
      keep: "true"

運用ベストプラクティス:①本番・ステージングの永続volumeにはkeep=true必ず付与、②テスト用・一時用にはephemeral=true付与、③prune時は必ず--filter "label=ephemeral=true"指定、④定期的にdocker volume ls --filter "dangling=true"で孤児確認、⑤本番volume変更前にバックアップ取得。

よくあるトラブルと対処

①volumeをマウントしたのに空

原因はvolumeの初期化タイミング。新規volumeをマウントした最初のコンテナ起動時のみ、コンテナイメージ内の対象パスのファイルがvolumeにコピーされます。既存volumeがあった場合はvolumeの内容が優先されるため「空」のvolumeを使うと中身がない。解決:一度docker volume rmして再作成するか、既存データをtar経由で投入。

②Permission denied

UID/GID不整合の対処
# SELinux(Fedora/RHEL/CentOS)
docker run -v ./data:/data:z ...   # :z で共有モード

# UID不一致
docker run --user "$(id -u):$(id -g)" ...
docker run -v my_vol:/data alpine chown -R 1000:1000 /data

# bind mount専用の回避策
chmod -R 777 ./bind_dir   # 開発中のみ(本番NG)

③DiskがFull

ディスク使用量確認
# Docker全体の使用量
docker system df
docker system df -v    # 詳細(volumeごとのサイズ)

# 特定volumeのサイズ
docker run --rm -v my_vol:/data alpine du -sh /data

# 全未使用データ削除(注意:開発用のみ)
docker system prune -a --volumes

④macOS/Windowsでパフォーマンスが遅い

bind mountはmacOS/Windowsで遅いのが既知の問題。named volumeに切替:delegated:cached付与、node_modulesやvendorのような重いディレクトリはanonymous volumeで上書き、Docker Desktopのファイル共有設定でVirtioFS(macOS)/WSL2(Windows)を使うと劇的改善。

⑤誤ってdocker volume pruneでデータ喪失

バックアップからしか復旧できません。日次でtarmysqldumppg_dumpをS3等に送っていれば数分で戻せます。取ってなかった場合はextundeletetestdiskでDocker用ディスクから削除済みファイルサルベージを試みる最終手段のみ。本記事「backup/restore」セクションのパターン①④⑦を必ず運用に組み込みましょう

よくある質問

Qvolumeとbind mountはどう使い分ける?
A永続データ(DB/uploads/ログ)はvolume、開発中のソース/設定はbind mountが基本。volumeはDocker管理で性能が良く、ホストOSに依存せず移植性高い。bind mountはホストのファイルを直接編集したい時に便利。詳細は【Docker】bind mountとvolumeの違いと使い分けを参照。
Qコンテナを削除するとvolumeも消える?
Anamed volumeは削除されませんdocker rmしても残る)。明示的にdocker volume rmするか、docker compose down -vで削除しない限り保持されます。匿名volumeはdocker rm -vで一緒に消えるが、named volumeは別管理と覚えてください。
Qvolumeのバックアップはどうすれば?
Atar+helperコンテナが汎用的(本記事パターン①)。DBはアプリレベルダンプ(mysqldump/pg_dump、パターン③④)の方が整合性的に安全。クラウド運用ならS3ライフサイクルで自動世代管理(パターン⑦)。GitHub Actionsのscheduleで日次実行も可能。
Qnamed volumeの中身を直接編集したい
Aホスト側から直接触らないのが鉄則。docker run --rm -it -v my_vol:/data alpine shで一時コンテナ経由でアクセスするか、既存コンテナ内でdocker compose exec service bashで入ってください。/var/lib/docker/volumes/xxx/_dataを直接virmするとSELinux/UIDの整合が取れなくなります。
QComposeでvolumeを分離しないと何が起きる?
A./data:/var/lib/mysqlのようにbind mountでDBを持たせると、①OS依存(Windows/macOSでパフォーマンス劣化)、②UID/GID問題、③prune対象外で管理しづらい、④ホスト側エディタで誤編集して壊す、などのリスク。本番DBは必ずnamed volumeにしてください。
Qvolumeを別マシンにコピーしたい
Atar経由のscp(本記事「ホスト間移行」)が定番。ssh経由でtar czf - | ssh user@dest "tar xzf - -C ..."のパイプライン1行で完結します。稼働中のDBコンテナはstop+mysqldumpでアプリレベル転送が安全。
Qvolume driverでNFSを使うとき認証は?
ANFSはUIDベース認証なのでkrb5(Kerberos)対応driverを使うか、cifsdriverでusername/password指定が楽。どちらもdriver_opts.osec=krb5username=...を指定します。クラウドはCSIドライバ+IAMでの認証に移行するのが2026年的。
Qvolume prune で消えないvolumeがある
A稼働中コンテナに参照されているvolumeは削除対象外です。停止している場合でも、そのコンテナがexit状態で残っていれば保持されます。本当に不要ならdocker rm $(docker ps -aq)でexit状態のコンテナを先に削除してからdocker volume pruneすれば消えます。
QKubernetesに移行するときvolumeは?
ADocker volumeは直接Kubernetesに持ち込めません。KubernetesではPersistentVolume (PV)PersistentVolumeClaim (PVC)StorageClassの仕組みを使います。kompose convertでcompose.ymlをマニフェストに変換できますが、volume部分は手動調整が必要。データ本体はtar→NFS/EBSに移してPVでマウントする形が典型です。
Q開発中ずっとanonymous volumeがたまる
Adocker volume ls -qf "dangling=true"で孤児を洗い出し、docker volume rm $(docker volume ls -qf "dangling=true")で一括削除。イメージのVOLUME宣言(VOLUME /var/lib/mysql等)がある場合、compose.ymlで必ずnamed volumeを指定しておくと新規作成が防げます。

関連記事

まとめ

  • コンテナのデータ永続化はnamed volumeが第一選択
  • 実体は/var/lib/docker/volumes/<name>/_data(macOS/WinはVM内部)
  • マウント5種:named/anonymous/bind/tmpfs/npipe、用途で選ぶ
  • 2026年推奨は--mount type=volume,source=...,target=...構文(意図明示)
  • Composeではexternal: truelabelsdriver_optsで運用管理
  • NFS/cifs/EBS等はdriver_optsで接続、ただしマルチホストはK8s推奨
  • バックアップ7パターン:tar/アプリダンプ/helperコンテナ/S3を使い分け
  • ホスト間移行はtar | ssh | tarの1行パイプで完結(DBはstop or ダンプ必須)
  • UID/GID問題は--userchownPUID/PGIDで解決
  • SELinuxは:z:Z、macOS/Win遅延は:delegated
  • 誤削除防止はlabels+prune --filterで物理的に守る
  • ディスク枯渇時はdocker system df -vで診断→個別削除

volumeは「データを失わないための基盤」として、本番/開発を問わず必須のコンポーネント。本記事のバックアップ7パターンとホスト間移行手順をスクリプト化しておけば、人為ミス・ホスト障害・クラウド移行のいずれでも数分でデータを復旧できます。bind mountとの使い分けComposeでの運用mysqldumpアプリレベルバックアップと組み合わせて、堅牢なコンテナ運用基盤を作ってください。