「docker-compose downしたら、MySQLのデータが全部消えた。バックアップはどう取ればいい?」
コンテナを止めてもデータが消えない仕組みがnamed volumeです。しかし、サーバー自体が壊れた場合や誰かが
docker volume rmを実行してしまった場合は、named volumeごとデータが失われます。この記事では、named volumeをtarアーカイブでバックアップする手順と、別サーバーへの移行・復元の方法を解説します。コンテナを停止してバックアップする安全な方法、停止できない場合のダーティコピー、cronによる定期バックアップ自動化、PostgreSQLの実践例まで体系的にカバーします。
実行環境:Rocky Linux 9.4 / Ubuntu 24.04 LTS、Docker 26.1.x
この記事のポイント
・named volumeのバックアップは docker run --rm -v で一時コンテナを使うのが定石
・本番DBは必ず停止バックアップ。停止できない場合は pg_dump / mysqldump を使う
・別サーバーへの移行は tar + rsync/scp の2ステップで完結する
・cronで夜間に自動バックアップすれば、誤削除・障害時に数分で復元できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜDockerボリュームのバックアップが必要なのか
Dockerのnamed volumeは、コンテナを削除してもデータが消えない設計です。しかし、次のような状況ではnamed volume自体が失われ、復元できなくなります。・誤操作:
docker volume rmやdocker system prune --volumesを誤って実行した・ホスト障害:Dockerが稼働しているLinuxサーバーのディスクが壊れた
・サーバー移行:VPSの乗り換えや別AZへの移行でコンテナを新規作成する必要がある
named volumeは物理的には
/var/lib/docker/volumes/ボリューム名/_data/に格納されています。このディレクトリをtarで圧縮してバックアップしておけば、どのような状況でも復元できます。named volumeのバックアップ対象を確認する
1. docker volume lsでボリュームを一覧表示する
まず、現在のDocker環境に存在するボリュームを確認します。# named volumeの一覧 $ docker volume ls DRIVER VOLUME NAME local myapp_pgdata local myapp_redis_data local wordpress_db_data
DRIVERがlocalのものが、通常のnamed volumeです。myapp_pgdataのようにCompose起動時に自動作成されるボリューム名には、プロジェクト名がプレフィックスとして付きます。2. docker volume inspectでMountpointを確認する
バックアップ対象のボリュームが、ホスト上のどこに格納されているか確認します。# ボリュームの詳細確認 $ docker volume inspect myapp_pgdata [ { "CreatedAt": "2026-07-15T10:23:45Z", "Driver": "local", "Labels": { "com.docker.compose.project": "myapp", "com.docker.compose.version": "2.27.0", "com.docker.compose.volume": "pgdata" }, "Mountpoint": "/var/lib/docker/volumes/myapp_pgdata/_data", "Name": "myapp_pgdata", "Options": {}, "Scope": "local" } ]
"Mountpoint"が実際のデータ格納パスです。このパスをLinuxのtarで直接アーカイブすることも可能ですが、一時コンテナ(--rm)経由でバックアップするのが推奨手順です。コンテナのファイルシステムマウント状態が正確に再現され、パーミッションの欠損が起きにくいためです。コンテナを停止してnamed volumeをバックアップする(推奨)
1. バックアップ前にコンテナを停止する
DBデータを扱う場合、コンテナが稼働中だとデータが書き込み途中の状態でコピーされる可能性があります。整合性を保つため、まずコンテナを停止します。# Composeを使っている場合(upで起動したサービス全体を停止) $ docker compose -f /opt/myapp/docker-compose.yml stop # 個別コンテナを指定して停止 $ docker stop myapp_postgres_1
2. 一時コンテナでtarアーカイブを作成する
named volumeのバックアップには、一時コンテナ(--rm)を使ってvolumeをマウントし、tarで圧縮する手法が定石です。# バックアップ保存先ディレクトリを作成 $ mkdir -p /backup/docker # named volumeをtarでバックアップ $ docker run --rm -v myapp_pgdata:/data:ro -v /backup/docker:/backup alpine tar czf /backup/myapp_pgdata_20260810.tar.gz -C /data . # 保存確認 $ ls -lh /backup/docker/myapp_pgdata_20260810.tar.gz -rw-r--r-- 1 root root 184M Aug 10 02:00 /backup/docker/myapp_pgdata_20260810.tar.gz
・
-v myapp_pgdata:/data:ro:named volumeを一時コンテナの/dataに読み取り専用でマウント・
-v /backup/docker:/backup:ホスト側のバックアップディレクトリをマウント・
alpine:軽量なAlpineイメージを一時コンテナとして使用(tarが標準内蔵)・
tar czf /backup/xxx.tar.gz -C /data .:/data(volumeの中身)をgzip圧縮でアーカイブ化する3. バックアップ後にコンテナを再起動する
# Composeを使っている場合 $ docker compose -f /opt/myapp/docker-compose.yml start # 個別コンテナの場合 $ docker start myapp_postgres_1
コンテナを止めずにバックアップする(ダーティコピー)
24時間稼働が求められるサービスで「コンテナを止められない」という場合もあります。その場合は、整合性が保証されない「ダーティコピー」としてバックアップを取ります。# コンテナ稼働中でもバックアップ可能(ただし整合性は保証されない) $ docker run --rm -v myapp_pgdata:/data:ro -v /backup/docker:/backup alpine tar czf /backup/myapp_pgdata_dirty_20260810.tar.gz -C /data .
・DBファイルは整合性が取れない状態でコピーされる可能性があります(トランザクション途中のデータが混入する)
・PostgreSQLやMySQLの場合は、ダーティコピーではなく後述の
pg_dump/mysqldumpを使うのが正しい選択です・静的ファイル(WordPressのアップロードファイル等)であれば、ダーティコピーでも実用上問題ないケースが多いです
Dockerのボリューム設計を実務で体系的に身につけたい方は、Docker実践講座(docker.linuxmaster.jp)をご覧ください。現役エンジニアが現場目線で教えるDockerの基礎から本番設計まで、ハンズオン形式で学べます。
→ Dockerマスター講座の詳細はこちら >>
バックアップから別サーバーへ復元する手順
1. バックアップファイルを新サーバーへ転送する
scpまたはrsyncでバックアップファイルを新サーバーへ転送します。# scp で転送(新サーバーのIPが 192.168.10.20 の場合) $ scp /backup/docker/myapp_pgdata_20260810.tar.gz user@192.168.10.20:/backup/ # rsync を使う場合(差分転送・再開可能) $ rsync -avz --progress /backup/docker/myapp_pgdata_20260810.tar.gz user@192.168.10.20:/backup/
2. 新サーバーでnamed volumeを作成して復元する
新サーバー側で作業します。ボリュームを先に作成してから、tarアーカイブを展開します。# 新サーバー側の作業 # 同名のnamed volumeを事前に作成する $ docker volume create myapp_pgdata # 一時コンテナでtarを展開してvolumeへ復元 $ docker run --rm -v myapp_pgdata:/data -v /backup:/backup alpine tar xzf /backup/myapp_pgdata_20260810.tar.gz -C /data # 復元確認(ファイルが展開されているか確認) $ docker run --rm -v myapp_pgdata:/data:ro alpine ls -la /data total 44 drwx------ 19 systemd-coredump root 4096 Aug 10 01:55 . drwxr-xr-x 1 root root 4096 Aug 10 02:05 .. drwx------ 5 systemd-coredump root 4096 Aug 10 01:55 base drwx------ 2 systemd-coredump root 4096 Aug 10 01:55 global drwx------ 2 systemd-coredump root 4096 Aug 10 01:55 pg_commit_ts
3. コンテナを起動して動作確認する
# 新サーバーでdocker compose up $ docker compose -f /opt/myapp/docker-compose.yml up -d # PostgreSQLへ接続してデータを確認 $ docker compose exec postgres psql -U postgres -c "\l" $ docker compose exec postgres psql -U postgres -d mydb -c "SELECT count(*) FROM users;" count ------- 1234 (1 row)
cronで定期バックアップを自動化する方法
手動バックアップだけでは人的ミスのリスクが残ります。cronで夜間に自動バックアップするスクリプトを組みましょう。# /opt/scripts/docker-volume-backup.sh として保存 #!/bin/bash set -euo pipefail BACKUP_DIR="/backup/docker" DATE=$(date +%Y%m%d_%H%M%S) COMPOSE_FILE="/opt/myapp/docker-compose.yml" VOLUME_NAME="myapp_pgdata" RETAIN_DAYS=7 mkdir -p "${BACKUP_DIR}" # コンテナを一時停止 docker compose -f "${COMPOSE_FILE}" stop # バックアップ実行 docker run --rm -v "${VOLUME_NAME}:/data:ro" -v "${BACKUP_DIR}:/backup" alpine tar czf "/backup/${VOLUME_NAME}_${DATE}.tar.gz" -C /data . # コンテナを再起動 docker compose -f "${COMPOSE_FILE}" start # 7日より古いバックアップを削除 find "${BACKUP_DIR}" -name "${VOLUME_NAME}_*.tar.gz" -mtime +"${RETAIN_DAYS}" -delete echo "[$(date)] Backup completed: ${BACKUP_DIR}/${VOLUME_NAME}_${DATE}.tar.gz"
# 実行権限付与 $ chmod 755 /opt/scripts/docker-volume-backup.sh # crontabを編集(rootで実行) $ sudo crontab -e # 毎日午前2時にバックアップ実行(結果をログに記録) 0 2 * * * /opt/scripts/docker-volume-backup.sh >> /var/log/docker-backup.log 2>&1
PostgreSQLボリュームのバックアップ実践例
PostgreSQLのデータはDB固有の内部形式で格納されているため、tarコピーだけでは復元に失敗するケースがあります。特にPostgreSQLのメジャーバージョンが異なる環境への移行ではpg_dumpを使ったSQLダンプ方式が確実です。1. pg_dumpでSQLダンプを取得する
docker compose execを使えば、コンテナを停止せずにSQLダンプを取得できます。# PostgreSQLコンテナからSQLダンプを取得(コンテナ稼働中でも可) $ docker compose exec postgres pg_dump -U postgres -Fc mydb > /backup/docker/mydb_20260810.dump # gzip 形式で保存する場合 $ docker compose exec postgres pg_dump -U postgres mydb | gzip > /backup/docker/mydb_20260810.sql.gz # バックアップサイズ確認 $ ls -lh /backup/docker/mydb_20260810.dump -rw-r--r-- 1 user user 42M Aug 10 02:05 /backup/docker/mydb_20260810.dump
-FcはPostgreSQLのカスタム形式で、pg_restoreで並列リストアが可能です。2. 別サーバーのPostgreSQLへリストアする
# ダンプファイルを新サーバーへ転送 $ scp /backup/docker/mydb_20260810.dump user@192.168.10.20:/backup/ # 新サーバーでPostgreSQLコンテナを起動(DBは空の状態で) $ docker compose up -d postgres # pg_restoreでリストア(-Fcカスタム形式の場合) $ cat /backup/mydb_20260810.dump | docker compose exec -T postgres pg_restore -U postgres -d mydb # gzip形式の場合は gunzip で展開しながらパイプ $ gunzip -c /backup/mydb_20260810.sql.gz | docker compose exec -T postgres psql -U postgres -d mydb # データ確認 $ docker compose exec postgres psql -U postgres -d mydb -c "SELECT count(*) FROM users;"
トラブルシュート・よくある失敗
「Permission denied」でtarが失敗する
named volume内のファイルがrootまたは特定のUIDで所有されている場合、alpineコンテナ内でアクセス拒否になることがあります。# --user rootを明示してtarを実行する $ docker run --rm --user root -v myapp_pgdata:/data:ro -v /backup/docker:/backup alpine tar czf /backup/myapp_pgdata_20260810.tar.gz -C /data .
復元後にPostgreSQLが起動しない(データ形式の不一致)
tarコピーでPostgreSQLを復元した場合、DBのメジャーバージョンが異なるとデータ形式の互換性問題が起きます。バージョンをまたぐ移行は必ずpg_dump/pg_restoreを使用してください。また、PostgreSQLのページサイズ(デフォルト8KB)が変更されている環境では復元に失敗することがあります。移行元と移行先のイメージバージョンが同じであることを確認してから復元してください。
volumeが見つからないとエラーが出る
# エラー例 Error response from daemon: invalid mount config for type "volume": no such volume: myapp_pgdata # 対処:volumeを先に作成してから復元コマンドを実行する $ docker volume create myapp_pgdata $ docker run --rm -v myapp_pgdata:/data -v /backup:/backup alpine tar xzf /backup/myapp_pgdata_20260810.tar.gz -C /data
本記事のまとめ
Dockerのnamed volumeバックアップと復元・移行の手順をまとめます。| やりたいこと | コマンド・手順 |
|---|---|
| ボリューム一覧を確認する | docker volume ls |
| ボリュームの格納先を確認する | docker volume inspect ボリューム名 |
| named volumeをtarでバックアップ | docker run --rm -v ボリューム名:/data:ro -v /backup:/backup alpine tar czf /backup/xxx.tar.gz -C /data . |
| tarから復元する | docker run --rm -v ボリューム名:/data -v /backup:/backup alpine tar xzf /backup/xxx.tar.gz -C /data |
| PostgreSQLのSQLダンプを取得する | docker compose exec postgres pg_dump -U postgres -Fc mydb > backup.dump |
| SQLダンプからリストアする | cat backup.dump | docker compose exec -T postgres pg_restore -U postgres -d mydb |
| cronで定期バックアップを自動化する | シェルスクリプト化してsudo crontab -eで登録 |
Dockerボリューム管理を現場で使いこなすには、Linux基盤の理解が土台になります
named volumeのバックアップはLinuxのtarコマンドとファイルシステムの知識が基礎です。/var/lib/docker/volumes/の構造やMountpointの意味を理解しておくと、障害時の復旧が格段に速くなります。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Dockerのgraceful shutdown設計|STOPSIGNALとstop_grace_periodでコンテナを安全に終了させる方法
- この記事の属するカテゴリ:Dockerへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます