Dockerボリュームをバックアップ・リストアしてみた

# はじめに
Dockerボリュームのバックアップ方法について試してみました
ググるとよく見つかるのが、以下①の手段なんですが、②でも出来るような気がしたので試してみました

　① 別の軽量Linuxコンテナとボリュームマウント、バインドマウントを使ってバックアップ
　② ボリュームごとホストへコピー

# 結果
無事①②両方ともでバックアップもリストアも出来ましたが、[Docker ドキュメント日本語化プロジェクト](https://docs.docker.jp/storage/index.html#id2)に以下の記載があったので、
>ボリューム（volume） は、 「Docker によって管理されている」ホストファイルシステム上の一部に保管します（ Linux 上では /var/lib/docker/volumes ）。  **Docker 以外のプロセスは、このファイルシステム上の一部を変更すべきではありません。** ボリュームは Docker 内のデータを保持するために一番良い方法です。

②で対応する場合は、私が検証したような後述する手段（xcopy等）は避けて、`docker cp`等を用いるべきなんだと思います。でもまぁ、ググると①ばかり見つかるので、結局は①に落ち着きそうです。

# 検証してみる
### 今回検証するコンテナとボリュームの構成
![docker_wordpress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/37abdfda-a17e-7292-b6c1-6675edc7d5e0.png)

### 先に②の検証
まずはコンテナを止めます
```console:コンテナ停止
$docker stop wordpress01
$docker stop mysql01
```

続いてボリュームをホストPCの任意のディレクトリへ退避します
なおボリュームは、Docker Desctop for Windowsだと`\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes`にあるので、これをコピーするだけです
```console:ボリュームをホストPCへコピー
$ xcopy \\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\wp-data .\wp-data /E/H/C/I

$ xcopy \\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\db-data .\db-data /E/H/C/I
```

コンテナとボリュームを削除します
```console:コンテナとボリュームの削除
$ docker rm wordpress01
$ docker rm mysql01

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
wp-data
db-data
```

ホストPCに退避したデータをボリュームへコピーします
```console:退避したデータをボリュームへコピー
$ xcopy .\db-data \\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\db-data /E/H/C/I

$ xcopy .\wp-data \\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\wp-data /E/H/C/I
```

リストアの確認のためにコンテナとボリュームを作ります
```console:コンテナとボリュームを作成
$ docker volume create db-data
$ docker volume create wp-data

$ docker run --restart=always --name mysql01 -dit --net=wp_network01 -v db-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=db -e MYSQL_USER=user -e MYSQL_PASSWORD=pass mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password
$ docker run --restart=always --name wordpress01 -dit --net=wp_network01 -v wp-data:/var/www/html -p 8080:80 -e WORDPRESS_DB_HOST=mysql01 -e WORDPRESS_DB_NAME=db -e WORDPRESS_DB_USER=user -e WORDPRESS_DB_PASSWORD=pass wordpress
```

http://localhost:8080/ へアクセスすると、バックアップした時点の状態でWordPressが表示されました

### 続いて①の検証

MySQL側だけの図ですが、こんな感じバックアップ用にbusyboxコンテナを作ります（割愛してますが、WordPressも同じイメージです）
![docker_wp_backup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/1a3a4b38-691b-b555-847c-2ff87a960434.png)

こちらも、まずはコンテナを止めます
```console:コンテナ停止
$docker stop wordpress01
$docker stop mysql01
```

バックアップです
- 軽量のLinuxコンテナ(今回はbusybox)を使ってバックアップします
このコンテナはすぐに削除するので`--rm`オプションをつけています
- busyboxコンテナですが、バックアップ元をボリューム指定することに加え、バックアップ先にバインドマウントを指定するところがポイントになるのかと

```console:書式
docker run --rm -v <バックアップ元(ボリューム)> -v <バックアップ先(バインドマウント)> busybox tar <tarコマンドのオプション>
```
```powershell:MySQLのバックアップ（Power Shellで実行してます。コマンドプロンプトだと、$や(が使えないので）
$ docker run --rm -v db-data:/var/lib/mysql -v ${pwd}/bkp:/db-bkp busybox tar czvf /db-bkp/db_backup.tar.gz -C /var/lib/mysql .
```
```powershell:WordPressのバックアップ（Power Shellで実行してます）
$ docker run --rm -v wp-data:/var/www/html -v ${pwd}/bkp:/wp-bkp busybox tar czvf /wp-bkp/wp_backup.tar.gz -C /var/www/html .
```
コンテナとボリュームを削除します
```console:コンテナとボリュームの削除
$ docker rm wordpress01
$ docker rm mysql01

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
wp-data
db-data
```

リストアです。バックアップとはtarのオプションが異なるだけ
```powershell:MySQLのリストア（Power Shellで実行してます）
$ docker run --rm -v db-data:/var/lib/mysql -v ${pwd}/bkp:/db-bkp busybox tar xzvf /db-bkp/db_backup.tar.gz -C /var/lib/mysql
```
```powershell:WordPressのリストア（Power Shellで実行してます）
$ docker run --rm -v wp-data:/var/www/html -v ${pwd}/bkp:/wp-bkp busybox tar xzvf /wp-bkp/wp_backup.tar.gz -C /var/www/html
```
リストアの確認のためにコンテナとボリュームを作ります
```console:コンテナとボリュームを作成
$ docker volume create db-data
$ docker volume create wp-data

$ docker run --restart=always --name mysql01 -dit --net=wp_network01 -v db-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=db -e MYSQL_USER=user -e MYSQL_PASSWORD=pass mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password
$ docker run --restart=always --name wordpress01 -dit --net=wp_network01 -v wp-data:/var/www/html -p 8080:80 -e WORDPRESS_DB_HOST=mysql01 -e WORDPRESS_DB_NAME=db -e WORDPRESS_DB_USER=user -e WORDPRESS_DB_PASSWORD=pass wordpress
```

http://localhost:8080/ へアクセスして、復元できていることを確認して終了です