Dockerボリュームのバックアップとリストア|tarで安全にデータを退避
4-2 で Named Volume を使ってデータを永続化しました。でもボリューム自体も消える事故はあります——ホストの故障、docker volume rm の誤爆、マシン移行、バージョンアップ前の保険。
この記事では、Docker公式が推奨する「一時コンテナを使った tar バックアップ」パターンと、そのリストア手順をマスターします。
💡 この記事のゴール
① なぜボリュームにバックアップが要るか
② 標準パターン:一時コンテナ + tar でバックアップ
③ リストア手順(既存ボリュームに展開 or 新ボリューム作成)
④ PostgreSQL ボリュームで実戦ハンズオン
⑤ DBは「停止してから」等の本番Tips
① なぜボリュームにバックアップが要るか
② 標準パターン:一時コンテナ + tar でバックアップ
③ リストア手順(既存ボリュームに展開 or 新ボリューム作成)
④ PostgreSQL ボリュームで実戦ハンズオン
⑤ DBは「停止してから」等の本番Tips
目次
- なぜボリュームをバックアップする?
- 基本パターン:一時コンテナで tar
- バックアップ手順
- リストア手順
- ハンズオン:Postgres ボリュームを退避→復元
- 本番運用のTips
- DB固有のダンプ併用
- まとめ
1. なぜボリュームをバックアップする?
| シナリオ | バックアップがないとどうなる? |
|---|---|
| マシン故障・SSD 物理破損 | 全ボリュームが読めず復旧不能 |
docker volume prune -a 誤爆 |
Named volume まで消える |
| Docker / OS のメジャーアップデート | データフォーマット非互換の可能性 |
| 開発用データを本番風にコピーしたい | バックアップがあれば数秒で別環境に展開 |
| 別ホストへの移行 | ボリュームを持ち運ぶ手段が必要 |
⚠️ 「ボリュームがあるから安心」ではない
Named Volume はコンテナの寿命を超えて生き残りますが、ホストそのものが故障したら一緒に消えます。重要データはホスト外(クラウドストレージ・別マシン)へ定期的に退避するのが原則です。
Named Volume はコンテナの寿命を超えて生き残りますが、ホストそのものが故障したら一緒に消えます。重要データはホスト外(クラウドストレージ・別マシン)へ定期的に退避するのが原則です。
2. 基本パターン:一時コンテナで tar
Dockerには docker volume backup というコマンドはありません。Docker公式が推奨しているのは次のパターンです。
【ボリュームバックアップの王道パターン】
🗄️ バックアップ元
mydata ボリューム
→
/source にマウント▶
🛠️ 一時コンテナ
alpine
tar czf を実行
tar czf を実行
終わったら
--rm で自滅▶
📦 バックアップ出力
ホストの
→
$(pwd)→
/backup にマウントmydata.tar.gz
↑ 軽量イメージ(alpine等)で使い捨てコンテナを立て、ボリュームとホスト側出力ディレクトリの両方をマウントして tar する
3. バックアップ手順
# mydata ボリュームを ./backup/mydata.tar.gz に退避
mkdir -p backup
docker run --rm \
-v mydata:/source:ro \
-v "$(pwd)/backup":/backup \
alpine \
tar czf /backup/mydata.tar.gz -C /source .
# 確認
ls -lh backup/mydata.tar.gz
| 部分 | 役割 |
|---|---|
--rm |
コマンド終了後に一時コンテナを自動削除 |
-v mydata:/source:ro |
ボリュームを読み取り専用でマウント(誤書込防止) |
-v "$(pwd)/backup":/backup |
ホスト側の出力ディレクトリを bind mount |
alpine |
tar が入っていて軽量(約7MB) |
tar czf ... -C /source . |
圧縮(c)・gzip(z)・ファイル指定(f)、ディレクトリ変更(-C)して相対パスで tar |
💡
tar ファイルには「パス」も記録されます。
-C /source . の意味tar ファイルには「パス」も記録されます。
-C なしだと source/file1 のような形で保存され、リストア時に変なパスができて面倒。-C /source . とすることで、アーカイブ内は ./file1 形式(相対パス)になり、どこにでも展開しやすくなります。
4. リストア手順
バックアップの逆向き——空のボリュームに tar を展開します。
# 1. リストア先のボリュームを用意(新規でもOK、既存でもOK)
docker volume create mydata-restored
# 2. 一時コンテナで tar を展開
docker run --rm \
-v mydata-restored:/dest \
-v "$(pwd)/backup":/backup:ro \
alpine \
sh -c "cd /dest && tar xzf /backup/mydata.tar.gz"
# 3. 中身の確認(別の一時コンテナで)
docker run --rm -v mydata-restored:/data alpine ls -la /data
⚠️ 既存ボリュームに上書きリストアする場合
mydata-restored が空でない場合、tar x は同名ファイルを上書きしますが、既存のファイルは消さない(差分上書き)。まっさらに戻したいなら、先に sh -c "rm -rf /dest/* && tar xzf ..." のように掃除してから展開します。
5. ハンズオン:Postgres ボリュームを退避→復元
4-2 で使った pgdata ボリュームを実際にバックアップ&リストアしてみます。
5-1. データ投入(準備)
docker volume create pgdata
docker run -d --name db \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
docker exec -it db psql -U postgres -c "CREATE TABLE users(id SERIAL PRIMARY KEY, name TEXT);"
docker exec -it db psql -U postgres -c "INSERT INTO users(name) VALUES ('Alice'),('Bob');"
5-2. Postgres を「停止してから」バックアップ
# 整合性のため、書き込み中のDBは停止する
docker stop db
# バックアップ
mkdir -p backup
docker run --rm \
-v pgdata:/source:ro \
-v "$(pwd)/backup":/backup \
alpine \
tar czf /backup/pgdata.tar.gz -C /source .
ls -lh backup/pgdata.tar.gz
# バックアップ完了後、DBを再開
docker start db
⚠️ DBは停止してからバックアップ
Postgres のデータファイルをコピー中に書き込みが入ると、部分的に壊れたアーカイブになる恐れがあります。書き込みが止まる状態を作ってから tar を取るのが基本。どうしても停止できない本番環境では、後述の
Postgres のデータファイルをコピー中に書き込みが入ると、部分的に壊れたアーカイブになる恐れがあります。書き込みが止まる状態を作ってから tar を取るのが基本。どうしても停止できない本番環境では、後述の
pg_dump 等の論理バックアップを使います。
5-3. 事故シミュレーション:ボリュームを消してしまう
docker rm -f db
docker volume rm pgdata # 😱 大事なボリュームを誤削除
docker volume ls
# pgdata が消えている
5-4. バックアップから復元
# 新規ボリュームを作る
docker volume create pgdata
# tar を展開
docker run --rm \
-v pgdata:/dest \
-v "$(pwd)/backup":/backup:ro \
alpine \
sh -c "cd /dest && tar xzf /backup/pgdata.tar.gz"
# Postgres を再起動して確認
docker run -d --name db \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# データ確認
docker exec -it db psql -U postgres -c "SELECT * FROM users;"
# id | name
# ----+-------
# 1 | Alice
# 2 | Bob
# (2 rows) ← 完全復活🎉
✅ 実証完了
ボリューム自体を削除してしまった状況から、tar バックアップだけで元の DB 状態に復元できました。これが最低限の「事故保険」です。
ボリューム自体を削除してしまった状況から、tar バックアップだけで元の DB 状態に復元できました。これが最低限の「事故保険」です。
6. 本番運用のTips
| ポイント | 内容 |
|---|---|
| スケジュール化 | cron / systemd timer / CI cronjob で1日1回 tar を作り、S3 等に転送 |
| 世代管理 | ファイル名に日付を含める:mydata-$(date +%Y%m%d).tar.gz。古いものは自動削除ルールで |
| オフサイト保管 | ホスト故障を想定し、クラウド(S3/GCS/OneDrive)や別マシンへ必ず転送 |
| リストアを定期的に試す | バックアップが取れていても、復元できなければ意味がない。年1は模擬復元を |
| 整合性ハッシュ | sha256sum mydata.tar.gz > mydata.tar.gz.sha256 を並べて保管 |
| DBはダンプ併用 | ボリュームtarは「物理」、pg_dump等は「論理」。両方取るのが最強 |
7. DB固有のダンプ併用
DBのボリュームtarは「データディレクトリの物理コピー」です。これに加えて、DBネイティブの論理ダンプも取っておくと安心です。
PostgreSQL
# 動作中の Postgres から論理ダンプを取る(停止不要・オンラインバックアップ)
docker exec -t db pg_dumpall -U postgres > backup/db-$(date +%Y%m%d).sql
# リストア
cat backup/db-20260420.sql | docker exec -i db psql -U postgres
MySQL
docker exec -t mysql-db mysqldump -uroot -psecret --all-databases \
> backup/mysql-$(date +%Y%m%d).sql
cat backup/mysql-20260420.sql | docker exec -i mysql-db mysql -uroot -psecret
💡 物理 vs 論理の使い分け
・物理(tarバックアップ):早い・全データ一括・DBバージョンを合わせれば瞬時に復元
・論理(pg_dump 等):遅め・SQLテキスト・別DB(別バージョン・別ホスト)への移植可能
本番では両方取るのが定石です。
・物理(tarバックアップ):早い・全データ一括・DBバージョンを合わせれば瞬時に復元
・論理(pg_dump 等):遅め・SQLテキスト・別DB(別バージョン・別ホスト)への移植可能
本番では両方取るのが定石です。
8. まとめ
| 押さえどころ | 内容 |
|---|---|
| 公式コマンドはない | 「一時コンテナ + tar」が Docker公式推奨パターン |
| バックアップ | docker run --rm -v vol:/source:ro -v $(pwd)/backup:/backup alpine tar czf /backup/xxx.tar.gz -C /source . |
| リストア | docker run --rm -v vol:/dest -v $(pwd)/backup:/backup:ro alpine sh -c "cd /dest && tar xzf /backup/xxx.tar.gz" |
| DBは停止する | 書き込み中の物理コピーは壊れやすい。停止 or ダンプ併用 |
| オフサイト保管 | ホスト故障に備え、別マシン or クラウドへ定期転送 |
| 復元演習 | 「取れていても復元できない」が最悪。定期的に試す |
✅ 次のステップ
第4章はこれで終わりです!永続化の4つのピース(エフェメラル理解・Named Volume・Bind Mount・tmpfs・バックアップ)が揃いました。次の第5章 ネットワークでは、コンテナ同士をつなぎ・外から叩くための仕組み(ブリッジ・DNS名前解決・ポートバインディング)を学びます。
第4章はこれで終わりです!永続化の4つのピース(エフェメラル理解・Named Volume・Bind Mount・tmpfs・バックアップ)が揃いました。次の第5章 ネットワークでは、コンテナ同士をつなぎ・外から叩くための仕組み(ブリッジ・DNS名前解決・ポートバインディング)を学びます。
参考リンク
- Back up, restore, or migrate data volumes(Docker公式) — 本記事のパターンの公式解説。
- PostgreSQL: SQL Dump(公式) —
pg_dump/pg_dumpallの使い方。 - MySQL: mysqldump(公式) — MySQL 論理バックアップの一次情報源。



コメント