言語を切り替える
テーマを切り替える

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

去年のダブルイレブン(独身の日セール)、会社が阿里云から腾讯云へのサーバー移行を決定しました。社長が突然、「Dockerに入ってるあのデータベース、どうするんだ?」と聞いてきました。正直に言うと、心臓が止まるかと思いました。半年間稼働させてきたPostgreSQLコンテナ、中には数GBの大切なユーザーデータが入っていますが、バックアップなんて一度も取っていなかったのです。

その夜、私は必死にDockerのバックアップ方法を検索しました。docker cptar コマンド、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 /data

x は解凍を意味します。それ以外はバックアップ時とほぼ同じです。

この方法のメリット:

  • あらゆるVolumeタイプに対応可能。
  • 圧縮できるのでディスク容量を節約できる(30〜50%縮小)。
  • バックアップファイルをそのままSCP等で別サーバーに転送できる。

注意点:
初めてこの方法を使った時、私は稼働中のMySQLコンテナに対して実行してしまいました。バックアップは成功しましたが、リストアしたら「テーブル破損」で起動しませんでした。データベースが書き込み中のときにファイルレベルのバックアップを取ると、不整合が起きる のです。

最も安全な手順:

  1. データベースへの書き込みを止める(コンテナ停止、またはテーブルロック)。
  2. バックアップを実行。
  3. サービス再開。

どうしても止められない場合は、データベース側の機能(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_temp

Nginxの設定変更前に、念のため 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:

動作フロー:

  1. 毎日AM2:00にバックアップコンテナが起動。
  2. postgres コンテナに stop-during-backup ラベルがあるので停止させる。
  3. db_data をtar圧縮。
  4. ホストの ./backups に保存。
  5. postgres コンテナを再開。
  6. 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.txt

3. データ転送

新サーバー(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 -d

5. 動作検証
ログ確認 (docker logs)、DB接続チェックを行い、データ件数が合っているか確認します。

私が踏んだ地雷:
以前、50GBのVolumeを docker run ... tar 経由で解凍したら1時間かかりました。実は、docker volume create した後、ホストの /var/lib/docker/volumes/... に直接root権限で解凍して配置するほうが速いです(ただしファイル権限の扱いに注意が必要)。

データベースバックアップの特記事項

データベース(MySQL, PostgreSQL)に関しては、ファイルシステムのバックアップ(Volumeバックアップ)だけでは不安な場合があります。

ファイルバックアップのリスク:
DB稼働中にtarバックアップを取ると、トランザクションログとデータファイルの整合性が取れず、復元時に起動しない可能性があります(InnoDBの破損など)。

より安全な「二重バックアップ」戦略:

  1. 論理バックアップ (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
  2. 物理バックアップ (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. 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. 2

    Step2: 方法3:ツールの自動化バックアップ

    docker-volume-backupツールの使用:
    1. Docker Composeにサービスを追加。
    2. environment変数でCRONスケジュール(例:"0 2 * * *")を設定。
    3. "stop-during-backup=true"ラベルで、バックアップ中のコンテナ停止を設定(整合性確保)。
    4. S3などへのアップロードも設定可能。
  3. 3

    Step3: サーバー移行ワークフロー

    1. 元サーバーで全コンテナ停止(docker-compose down)。
    2. 全Volumeをtarコマンドでバックアップ。
    3. rsyncやscpでバックアップファイルを新サーバーへ転送。
    4. 新サーバーでVolumeを作成し、tarを展開してデータをリストア。
    5. docker-compose up で起動し、データを検証。

FAQ

稼働中のデータベースコンテナをバックアップしても大丈夫ですか?
リスクがあります。データベースが書き込み処理を行っている最中にファイルレベルのバックアップ(tarなど)を取ると、データ不整合や破損の原因になります。安全のためには、一時的にコンテナを停止するか、データベースのロック機能を使用することをお勧めします。停止できない場合は、mysqldumpやpg_dumpなどの論理バックアップツールを使用してください。
tarバックアップとdocker cpの違いは何ですか?
tarはデータを圧縮して1つのファイルにまとめるため、保管や転送に有利で、権限情報も保持しやすいです。docker cpはファイルをそのままコピーするため、設定ファイルなどの小規模な取り出しには便利ですが、圧縮されず容量を食うのと、大量のファイルを扱うには不向きです。
Volumeバックアップとデータベースのダンプ(SQLエクスポート)、どっちが良いですか?
併用がベストです。「SQLダンプ」は整合性が高く、バージョン間の互換性もありますが、復元に時間がかかります。「Volumeバックアップ」は復元が非常に高速ですが、整合性のリスクがあります。本番環境では、SQLダンプをメインの復元手段にし、Volumeバックアップを災害復旧用の保険として両方取得するのが賢明です。

5 min read · 公開日: 2025年12月17日 · 更新日: 2026年1月22日

コメント

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

関連記事