最近色々セルフホスティングでコンテナ動かしているため、バックアップの必要が出てきた。ので、その内容と実際の手順についてメモする。
ボリュームのバックアップは何をやるのか
まずDockerのボリュームのバックアップとはつまり何をすることなのかについて。これは公式の「Back Up and Share Docker Volumes with This Extension | Docker」を読むとよいのだが、つまりは以下のスニペットに帰結する。
docker run --rm \
-v "$VOLUME_NAME":/backup-volume \
-v "$(pwd)":/backup \
busybox \
tar -zcvf /backup/my-backup.tar.gz /backup-volumeこのコードの詳細な解説はChatGPTに譲るが、まぁ要はバックアップを作るためのコンテナを作成し、ホストマシンにデータをコピーしている形だ。復元はこれの逆をやると良い。DBなんかは通常dumpのユーティリティがあるが、記事によればDockerの場合はこれでまるごとコピーするほうが良いとのことだ。
ChatGPTによるコードの解説
このコマンドは、Dockerを使って簡単にバックアップを作成するための手順です。以下に各部分の解説を行います。
docker run --rm:
docker runは Docker コンテナを実行するコマンドです。--rmは、コンテナが終了した後にそのコンテナを自動的に削除するオプションです。これにより、バックアップが完了した時点で不要なコンテナが残らないようになります。
-v "$VOLUME_NAME":/backup-volume:
-vオプションは、ホストマシンとコンテナ間でボリュームをマウントするためのものです。$VOLUME_NAMEはバックアップしたい Docker ボリュームの名前を指します。これがコンテナ内の/backup-volumeディレクトリにマウントされます。
-v "$(pwd)":/backup:
- こちらも
-vオプションですが、ホストマシンの現在の作業ディレクトリ($(pwd)で取得される)をコンテナ内の/backupディレクトリにマウントしています。このディレクトリにバックアップファイルを保存します。
busybox:
- これは Docker イメージの名前です。
busyboxは非常に軽量な Linux ベースのイメージで、基本的なユーティリティ(tarなど)を含んでいます。このコンテナが一時的に起動され、バックアップ処理を実行します。
tar -zcvf /backup/my-backup.tar.gz /backup-volume:
tarコマンドで圧縮ファイル(.tar.gz)を作成しています。-z:gzip形式で圧縮するオプション。-c: 新しいアーカイブを作成するオプション。-v: 詳細な出力(アーカイブ中のファイル名を表示する)。-f /backup/my-backup.tar.gz: 出力するファイル名を指定しています。この場合は、/backup/my-backup.tar.gzという名前で圧縮ファイルが作成されます。/backup-volume: アーカイブ対象のディレクトリで、マウントされたボリュームです。
まとめ:
このコマンドは、指定した Docker ボリューム($VOLUME_NAME)を tar コマンドで圧縮し、現在のディレクトリに my-backup.tar.gz という名前のバックアップファイルを保存します。
これを実行するものとして、v4.29.0以降のDocker Desktopでは拡張機能として公式で提供されている(「Volumes Backup & Share - Docker Extension | Docker Hub」)。上の記事によれば、この拡張機能はボリュームをアタッチしているコンテナを調べて一時停止し、再起動するところまで含めてやっているようだ。

便利な拡張機能だが、もうすぐdeprecatedになる見込みで、どうやらこの機能は近日中に公式で提供されるものらしい。その際、手動バックアップは普通に使えるが、スケジューリングはサブスクプラン専用機能になる模様(Explore Volumes | Docker Docs)。
CLIで無料でやりたい
バックアップはスケジューリングしてやりたいし、お金はないし、そもそもVPSとかDocker Desktopない環境でも使いたい。ということで、フツーにスクリプト書くかなと思った。
やっていることは単純なので、全部自分で書いてもよかったが、上記記事の中でも紹介されている「https://github.com/BretFisher/docker-vackup」がシンプルなシェルスクリプトでそのまま使えて便利そうだったので、これを使うことにした。
インストール手順はREADME.md見ればよいが一応書いておく。LinuxとMacならそのまんま。
sudo curl -sSL https://raw.githubusercontent.com/BretFisher/docker-vackup/main/vackup -o /usr/local/bin/vackup && sudo chmod +x /usr/local/bin/vackupこのスクリプトは特にコンテナの停止などしていないようなので、ユースケースから必要なら停止する処理を入れたスクリプト書くべし。
vackupを使ったバックアップと復元
いざという時に使えるように、練習する。
テスト用コンテナのセットアップ
テスト用のDockerネットワークを作成
docker network create test-networkMySQLコンテナを起動し、データを保存するためのVolumeを作成
docker run -d --name mysql-test \
--network test-network \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=testdb \
-v mysql-data:/var/lib/mysql \
mysql:latestデータの投入
MySQLコンテナに接続
docker exec -it mysql-test mysql -uroot -prootpasswordデータベース内にテーブルを作成し、データを挿入。SELECTクエリの結果に、バックアップ時に挿入したデータ (id = 1, data = 'backup test') が表示されることを確認する。
USE testdb;
CREATE TABLE test_table (id INT, data VARCHAR(100));
INSERT INTO test_table (id, data) VALUES (1, 'backup test');
SELECT * FROM test_tableバックアップの実行
vackup export mysql-data mysql-data.tar.gzコンテナとボリュームの削除
docker stop mysql-test
docker rm mysql-test
docker volume rm mysql-dataコンテナを再作成
docker run -d --name mysql-test \
--network test-network \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=testdb \
-v mysql-data:/var/lib/mysql \
mysql:latestMySQLコンテナに接続
docker exec -it mysql-test mysql -uroot -prootpasswordデータが空であることを確認する。
USE testdb;
SELECT * FROM test_table復元
コンテナの停止。
docker stop mysql-testボリュームの復元
vackup import mysql-test.tar.gz mysql-testMySQLコンテナを起動して接続
docker start mysql-test
docker exec -it mysql-test mysql -uroot -prootpasswordデータの確認。
USE testdb;
SELECT * FROM test_tableSELECTクエリの結果に、バックアップ時に挿入したデータ (id = 1, data = 'backup test') が表示されることを確認する。
復元OK。
以上。

コメント