Dockerボリュームのバックアップと移行ガイド:3つの実戦的手法

去年のダブルイレブン(独身の日セール)、会社が阿里云から腾讯云へのサーバー移行を決定しました。社長が突然、「Dockerに入ってるあのデータベース、どうするんだ?」と聞いてきました。正直に言うと、心臓が止まるかと思いました。半年間稼働させてきたPostgreSQLコンテナ、中には数GBの大切なユーザーデータが入っていますが、バックアップなんて一度も取っていなかったのです。
その夜、私は必死にDockerのバックアップ方法を検索しました。docker cp、tar コマンド、docker-volume-backup ツール……情報はたくさんありましたが、どれが正解なのか、本番環境で試してデータを壊さないか、不安で仕方ありませんでした。一番怖かったのは、バックアップ中にデータベースへの書き込みが発生して、壊れたバックアップファイルを作ってしまうことでした。
その後、何度か冷や汗をかきながら試行錯誤し、ようやくコツを掴みました。実はDockerのデータバックアップはそれほど複雑ではありません。重要なのは「どのシーンでどの方法を使うか」を知ることです。この記事では、私が実戦で学んだ3つの主要なバックアップ方法を紹介します。それぞれのメリット・デメリット、そして落とし穴を回避する方法も解説します。これを読めば、あなたのDocker環境に最適なバックアップ戦略が見つかるはずです。
なぜDockerデータのバックアップが重要なのか
Dockerのデータストレージの仕組み
Dockerを使い始めたばかりの人は、データストレージの仕組みを誤解しやすいです。コンテナが動けばデータもそこにある、と思いがちですが、最大のリスクは コンテナは本来、使い捨て(エフェメラル)である という点です。
データをコンテナ内部に直接書き込むと、コンテナを再起動したりイメージを更新したりした瞬間にデータは消えます。そのため、Dockerには2つの永続化手段が用意されています。
- Volume(ボリューム): Dockerが管理する保存領域(通常
/var/lib/docker/volumes/)。公式が推奨する方法で、権限管理やライフサイクルをDockerが面倒見てくれます。 - Bind Mount(バインドマウント): ホストマシンのディレクトリを直接コンテナにマウントする方法。
/home/user/dataをコンテナの/dataに繋ぐなど。場所が明確なのでバックアップしやすく感じますが、管理は自分で行う必要があります。
バックアップすべきデータは主に以下です:
- データベースファイル (PostgreSQL, MySQL, MongoDBなどのデータディレクトリ)
- ユーザーアップロードファイル (アイコン、ドキュメント、画像など)
- 設定ファイル (再構築可能ですが、複雑な設定はバックアップした方が安全)
- ログファイル (監査や分析が必要な場合)
よくあるデータ消失シナリオ
私が実際に目撃したり耳にしたりしたデータ消失事故は、大抵これらです。
手滑りによるコンテナ削除:一番多いです。「テスト用コンテナを消そう」と思って docker rm -v を叩いたら、-v オプションのせいで紐付いていた重要なデータボリュームまで消してしまった、というケース。私もやらかしたことがあります。
ディスク障害:サーバーだって機械です。突然HDDが壊れることもあります。RAIDを組んでいても、RAIDコントローラー自体が壊れることも。バックアップがあれば、新しいディスクに交換してリストアするだけで済みます。
サーバー移行:冒頭の話です。クラウドベンダーの変更、オンプレからクラウドへ、あるいはKubernetesへの移行。データをどう安全に運ぶかは大きな課題です。
ある友人のスタートアップでは、DBコンテナが原因不明のクラッシュを起こし、再起動したらデータが破損して起動しなくなりました。直近のバックアップは2ヶ月前。2ヶ月分の注文データが消え、数十万ドルの損失が出ました。
脅すわけではありませんが、定期バックアップは命綱です。データが消えたら、どんな技術力があっても取り戻せません。
3つのバックアップ方法徹底解説
方法1:tarコマンドによるバックアップ(⭐⭐⭐⭐⭐ 推奨)
最も汎用的で、私が一番よく使う方法です。核心的なアイデアはシンプルで、「Volumeをマウントした使い捨てコンテナを立てて、tarで固める」 というものです。
バックアップコマンド:
docker run --rm \
-v postgres_data:/data:ro \
-v $(pwd):/backup \
ubuntu tar czf /backup/postgres-backup-20251217.tar.gz -C /data .このコマンドを分解解説します:
--rm: バックアップが終わったらこの一時コンテナを自動削除します。ゴミを残しません。-v postgres_data:/data:ro: バックアップしたいVolume (postgres_data) をコンテナの/dataに読み取り専用 (:ro) でマウントします。誤操作を防ぐため重要です。-v $(pwd):/backup: カレントディレクトリをコンテナの/backupにマウント。ここにバックアップファイルが作られます。tar czf: アーカイブ作成(c)、gzip圧縮(z)、ファイル名指定(f)。-C /data .:/dataディレクトリに移動してから、その中身全て(.)を対象にします。
リストア(復元)コマンド:
docker run --rm \
-v postgres_data:/data \
-v $(pwd):/backup \
ubuntu tar xzf /backup/postgres-backup-20251217.tar.gz -C /datax は解凍を意味します。それ以外はバックアップ時とほぼ同じです。
この方法のメリット:
- あらゆるVolumeタイプに対応可能。
- 圧縮できるのでディスク容量を節約できる(30〜50%縮小)。
- バックアップファイルをそのままSCP等で別サーバーに転送できる。
注意点:
初めてこの方法を使った時、私は稼働中のMySQLコンテナに対して実行してしまいました。バックアップは成功しましたが、リストアしたら「テーブル破損」で起動しませんでした。データベースが書き込み中のときにファイルレベルのバックアップを取ると、不整合が起きる のです。
最も安全な手順:
- データベースへの書き込みを止める(コンテナ停止、またはテーブルロック)。
- バックアップを実行。
- サービス再開。
どうしても止められない場合は、データベース側の機能(WALログなど)が有効であることを確認してください。
実戦例:PostgreSQLデータのバックアップ
# 1. PostgreSQLコンテナを停止(可能なら)
docker stop my-postgres
# 2. Volumeをバックアップ
docker run --rm \
-v postgres_data:/data:ro \
-v /backup:/backup \
ubuntu tar czf /backup/pg-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .
# 3. ちゃんと作れたか確認
ls -lh /backup/pg-*.tar.gz
# 4. コンテナ再開
docker start my-postgresこのようにタイムスタンプを含めるのをお勧めします。
方法2:docker cp コマンド(⭐⭐⭐)
もっと直感的で、tarで固めずにファイルを直接吸い出す方法です。設定ファイルや小さなディレクトリには最適です。
バックアップ手順:
# 1. Volumeをマウントした一時コンテナを作成(起動はしない)
docker create -v nginx_config:/data --name temp_backup busybox
# 2. データをホストにコピー
docker cp temp_backup:/data ./nginx-config-backup
# 3. 一時コンテナを削除
docker rm temp_backupリストア手順:
# 新しいコンテナにデータをコピー
docker cp ./nginx-config-backup/. my-nginx:/etc/nginx/この方法のメリット:
- 解凍の手間がなく、中身をすぐ確認できる。
- 小さなファイルなら手軽。
デメリット:
- 圧縮されないので容量を食う。
- tarに比べて転送速度が遅い場合がある。
- 権限や特殊属性が完全に保持されないことがある。
実戦例:Nginx設定のバックアップ
# 一時コンテナ作成
docker create -v nginx_config:/config --name nginx_temp busybox
# 設定ファイルだけ取り出す
docker cp nginx_temp:/config/nginx.conf ./backup/
# またはディレクトリごと
docker cp nginx_temp:/config/. ./backup/nginx-config/
# 後始末
docker rm nginx_tempNginxの設定変更前に、念のため docker cp で現行設定を抜いておく、といった使い方が便利です。
方法3:自動化ツール docker-volume-backup(⭐⭐⭐⭐ 自動化の決定版)
手動バックアップは忘れます。本番環境ではツールによる 自動定期バックアップ が必須です。
現在私が愛用しているのは offen/docker-volume-backup です。2025年時点でのOSSの定番です。
- クーロン式(cron)でのスケジュール実行。
- バックアップ実行中に自動で対象コンテナを停止・再開(整合性確保)。
- S3, Google Drive, SSH, WebDAVなどへのアップロード対応。
- 古いバックアップの自動削除。
Docker Compose設定例:
version: '3.8'
services:
# データベースサービス
postgres:
image: postgres:15
volumes:
- db_data:/var/lib/postgresql/data
labels:
# バックアップ中にこのコンテナを停止するよう指示
- "docker-volume-backup.stop-during-backup=true"
# バックアップサービス
backup:
image: offen/docker-volume-backup:latest
environment:
# 毎日深夜2時に実行
BACKUP_CRON_EXPRESSION: "0 2 * * *"
BACKUP_FILENAME: "db-backup-%Y%m%d-%H%M%S.tar.gz"
# 7日分保存
BACKUP_RETENTION_DAYS: "7"
volumes:
# 対象データ(読み取り専用)
- db_data:/backup/db_data:ro
# バックアップ保存先
- ./backups:/archive
# コンテナ制御のためDockerソケットが必要
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
db_data:動作フロー:
- 毎日AM2:00にバックアップコンテナが起動。
postgresコンテナにstop-during-backupラベルがあるので停止させる。db_dataをtar圧縮。- ホストの
./backupsに保存。 postgresコンテナを再開。- 7日より古いバックアップを削除。
注意点:/var/run/docker.sock の権限に注意してください。また、サービスが一時的に停止します(データ量によるが数秒〜数十秒)。無停止が必要ならラベルを外しますが、その場合はデータの不整合リスクを受け入れる必要があります。
本番例:MongoDBのS3バックアップ
services:
backup:
image: offen/docker-volume-backup:latest
environment:
BACKUP_CRON_EXPRESSION: "0 3 * * *"
BACKUP_FILENAME: "mongo-%Y%m%d.tar.gz"
BACKUP_RETENTION_DAYS: "14"
# S3への転送設定
AWS_S3_BUCKET_NAME: "my-backups"
AWS_ACCESS_KEY_ID: "${AWS_KEY}"
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET}"
volumes:
- mongo_data:/backup/mongo_data:ro
- /var/run/docker.sock:/var/run/docker.sock:roこれでS3に半永久的にバックアップが残り、ローカルディスクを圧迫しません。
サーバー移行 完全ガイド
移行の実戦ステップ
バックアップ方法がわかったところで、サーバー移行(例:AサーバーからBサーバーへ)の全手順を整理します。
1. 現状調査(準備)
# 全コンテナ確認
docker ps -a
# 全Volume確認
docker volume ls
# 設定のエクスポート(超重要)
docker inspect my-postgres > postgres-config.json
cp docker-compose.yml docker-compose.backup.yml
cp .env .env.backup環境変数ファイル(.env)のバックアップを絶対に忘れないでください。私は一度これでDBパスワードがわからなくなり、冷や汗をかきました。
2. バックアップ実行
サービスを停止し、静止点バックアップを取ります。
docker-compose down
# Volumeをtar化
docker run --rm \
-v postgres_data:/data:ro \
-v $(pwd)/backups:/backup \
ubuntu tar czf /backup/postgres_data.tar.gz -C /data .
# 念のためMD5チェックサムを取る
md5sum backups/*.tar.gz > backups/checksums.txt3. データ転送
新サーバー(Bサーバー)へファイルを送ります。
# rsyncなら中断しても再開できるのでおすすめ
rsync -avP --partial backups/ user@new-server:/tmp/backups/4. 新サーバーでの復元
# 1. Volumeを先に作成
docker volume create postgres_data
# 2. データを展開
docker run --rm \
-v postgres_data:/data \
-v /tmp/backups:/backup \
ubuntu tar xzf /backup/postgres_data.tar.gz -C /data
# 3. 権限確認(postgresユーザーのUIDになっているか等)
docker run --rm -v postgres_data:/data ubuntu ls -lhn /data
# 4. サービス起動
docker-compose up -d5. 動作検証
ログ確認 (docker logs)、DB接続チェックを行い、データ件数が合っているか確認します。
私が踏んだ地雷:
以前、50GBのVolumeを docker run ... tar 経由で解凍したら1時間かかりました。実は、docker volume create した後、ホストの /var/lib/docker/volumes/... に直接root権限で解凍して配置するほうが速いです(ただしファイル権限の扱いに注意が必要)。
データベースバックアップの特記事項
データベース(MySQL, PostgreSQL)に関しては、ファイルシステムのバックアップ(Volumeバックアップ)だけでは不安な場合があります。
ファイルバックアップのリスク:
DB稼働中にtarバックアップを取ると、トランザクションログとデータファイルの整合性が取れず、復元時に起動しない可能性があります(InnoDBの破損など)。
より安全な「二重バックアップ」戦略:
- 論理バックアップ (SQLダンプ):アプリケーション整合性が確実。
# PostgreSQL docker exec my-postgres pg_dump -U postgres mydb > mydb.sql # MySQL docker exec my-mysql mysqldump -u root -p mydb > mydb.sql - 物理バックアップ (Volume tar):復元が速い、全体のバックアップ。
私は本番環境では必ず両方やります。pg_dump はメインの復元手段、Volumeバックアップはそれが失敗した時の「最後の砦」です。
ベストプラクティスとまとめ
バックアップの「3-2-1ルール」
- 3つのコピーを持つ(本番データ + バックアップ2つ)。
- 2種類のメディアに保存(ローカルディスク + クラウドなど)。
- 1つは遠隔地に置く(データセンター火災対策)。
私の設定例:
- ローカルサーバー:直近7日分を保持。
- NAS:直近30日分。
- S3(クラウド):直近3ヶ月分。
定期的なリストアテスト
バックアップがあっても、戻せなければ意味がありません。少なくとも月に1回は、テスト環境にバックアップからデータを戻して、正常に起動するか確認してください。「シュレーディンガーのバックアップ」(開けてみるまで状態が不明)は、いざという時にあなたを裏切ります。
結論
- 単発・移行なら tarコマンド。
- 小ファイルなら docker cp。
- 定期・本番なら 自動化ツール。
今日、まずは手動で tar バックアップを一度試してみてください。そのバックアップファイルが1つあるだけで、夜眠る時の安心感が劇的に変わりますよ。
Dockerデータボリューム・完全バックアップ&移行手順
tarアーカイブ、docker cp、自動化ツールを使った3種類のバックアップ方法と、サーバー移行時のリストア手順
⏱️ Estimated time: 1 hr
- 1
Step1: 方法1:tarコマンドによるバックアップ(推奨)
バックアップ手順:
1. docker run --rm -v volume_name:/data -v $(pwd):/backup ubuntu tar czf /backup/backup.tar.gz -C /data .
2. 一時コンテナがVolumeをマウントし、圧縮してホストの/backupに出力します。
リストア手順:
1. docker run --rm -v volume_name:/data -v $(pwd):/backup ubuntu tar xzf /backup/backup.tar.gz -C /data
2. データをVolumeに解凍します。 - 2
Step2: 方法3:ツールの自動化バックアップ
docker-volume-backupツールの使用:
1. Docker Composeにサービスを追加。
2. environment変数でCRONスケジュール(例:"0 2 * * *")を設定。
3. "stop-during-backup=true"ラベルで、バックアップ中のコンテナ停止を設定(整合性確保)。
4. S3などへのアップロードも設定可能。 - 3
Step3: サーバー移行ワークフロー
1. 元サーバーで全コンテナ停止(docker-compose down)。
2. 全Volumeをtarコマンドでバックアップ。
3. rsyncやscpでバックアップファイルを新サーバーへ転送。
4. 新サーバーでVolumeを作成し、tarを展開してデータをリストア。
5. docker-compose up で起動し、データを検証。
FAQ
稼働中のデータベースコンテナをバックアップしても大丈夫ですか?
tarバックアップとdocker cpの違いは何ですか?
Volumeバックアップとデータベースのダンプ(SQLエクスポート)、どっちが良いですか?
5 min read · 公開日: 2025年12月17日 · 更新日: 2026年1月22日
関連記事
Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践

Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践
Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド

Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド
Next.js ユニットテスト実践:Jest + React Testing Library 完全設定ガイド


コメント
GitHubアカウントでログインしてコメントできます