Dockerのvolumeのバックアップをするには、バックアップ用のコンテナでボリュームをマウントし、ファイルを取り出す操作が必要。
ホームラボの話なので、サービスが一時的に停止しても良いという前提で、雑なバックアップの手順を整理しておくことにした。
いま、ホームラボの中心となるサーバーで稼働しているのは、Samba ad dc、Kopano、Giteaの3システム。
それぞれのシステムごとにdocker-compose.ymlがあって、5つのコンテナが起動している。
コンテナを停止させずにバックアップするのであれば、違ったアプローチをしていくことになるが、コンテナを停止させられる環境なので、ボリューム丸ごとコピー方式とした。
コンテナのバックアップそのものはワンライナーでいけるけれど、
- 丸ごとコピーとはいえ、Samba ad dcでは拡張属性を取得しておく必要がある。
- 操作ミスでボリュームが消えてしまうのを防ぐため、3システムのボリュームを掴むコンテナを作っておきたい。
という理由で、コンテナを作り込むことにしている。
ワンライナーのご参考、ここではlsしてみている。
バックアップ用のボリュームをもう1つ用意して、そこにファイルをコピーするのが常套手段のようだ。
$ sudo docker run --rm -v samba_private:/mnt alpine:latest ls -la /mnt total 10236 drwxr-xr-x 7 root root 4096 Aug 21 04:36 . drwxr-xr-x 1 root root 4096 Aug 25 14:05 .. -rw------- 1 root root 2326 Aug 20 10:03 dns_update_cache -rw-r--r-- 1 root root 3663 Aug 20 10:03 dns_update_list …
ファイル構成
Samba ad dcでHOGEDOMAINというドメインを管理しているので、hd-backupというディレクトリを作り、そこにファイルを作っていく。
リポジトリはこちら。
~/hd-backup/ ├ baseimage/ │ └ Dockerfile ├ mkbaseimage.sh* ├ Dockerfile ├ docker-compose.yml ├ entrypoint.sh* ├ backup.sh* └ do-backup*
*実行権限を付ける
ベースとなるイメージの作成
バックアップにはAlpine Linuxを使わせていただくことにした。
サイズが小さくてありがたい。
Sambaは拡張属性のバックアップも取りたいのでsamba-toolが動かせるように、samba-dcパッケージをインストールする。
https://pkgs.alpinelinux.org/packages
このsamba-dcパッケージをインストールするのに、まぁまぁな量のダウンロードをするので、スクリプト差し替えを気軽に実行できるように、ベースイメージを作成することにした。
~/hd-backup/baseimage/Dockerfile
FROM alpine:latest RUN apk add samba-dc tzdata
ベースイメージを構築するためのスクリプトを作成する。
~/hd-backup/mkbaseimage.sh
#!/bin/bash cd $(dirname ${0}) sudo docker build -t custom/backup:0.0.1 -f $PWD/baseimage/Dockerfile .
スクリプトに実行権を付けて、実行する。
$ cd ~/hd-backup $ chmod +x mkbaseimage.sh $ ./mkbaseimage.sh $ sudo docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE custom/backup 0.0.1 a65abe7e79f3 41 minutes ago 153MB …
Dockerfile
ベースイメージにスクリプトを2つ登録。
- コンテナが起動したら動作するスクリプト。
- バックアップスクリプト。
~/hd-backup/Dockerfile
FROM custom/backup:0.0.1 ADD entrypoint.sh / Add backup.sh / ENTRYPOINT ["/entrypoint.sh"]
docker-compose.yml
Dockerfileでコンテナを作り、バックアップ対象となるボリュームをマウントするdocker-compose.ymlを作成する。
コンテナでvolumes指定をしているが、コンテナに存在しないディレクトリは作られるし、存在するディレクトリは置き換えられたような状態になる。
volumesの定義では、名前を明確に指定し、それが外部のボリュームであることを指定している。
バックアップ先は、ホストの /var/backups とした。
バックアップファイル名にホスト名を使用するので、hostnameを適宜設定。
拡張属性をバックアップするためNTACLを作成するが、samba-toolコマンドが/etc/samba/smb.confを読み込んで動作するようなので、マウントポイントはdocker-compose.ymlで正確に合わせた。
一方、KopanoとGiteaは単純にファイルをバックアップするだけなので、/tmp配下にマウントポイントを作成している。
~/hd-backup/docker-compose.yml
version: "3.9" services: backup: build: ./ image: custom/backup:1.0.0 container_name: backup restart: "no" environment: TZ: Asia/Tokyo DO_BACKUP: "true" hostname: hogedomain volumes: # Samba ad dc - samba_etc:/etc/samba - samba_lib:/var/lib/samba - bind_etc:/etc/bind - bind_lib:/var/lib/bind - lam:/var/lib/ldap-account-manager # Kopano - kopano:/tmp/kopano/var/lib/kopano/attachments - kopano_db:/tmp/kopano/var/lib/mysql # Gitea - gitea:/tmp/gitea/data - /home/git/.ssh:/tmp/gitea/data/git/.ssh - gitea_db:/tmp/gitea/var/lib/mysql # Backup directory - /var/backups:/mnt/backups volumes: bind_etc: name: samba_bind_etc external: true bind_lib: name: samba_bind_lib external: true lam: name: samba_lam external: true samba_etc: name: samba_samba_etc external: true samba_lib: name: samba_samba_lib external: true kopano: name: kopano_kopano external: true kopano_db: name: kopano_kopano_db external: true gitea: name: gitea_gitea external: true gitea_db: name: gitea_mysql external: true
entrypoint.sh
コンテナが起動すると呼び出され、バックアップスクリプトを実行して終了するだけのスクリプト。
リストアの場合は、起動後になかでゆっくりと操作をしたいと思ったので、DO_BACKUP変数にtrueが与えられなかった場合は、無限ループに入るようにした。
~/hd-backup/entrypoint.sh
#!/bin/ash echo "Start container with parameter : $@" trap sig_term SIGTERM sig_term() { echo "CATCH SIGTERM" wait exit 0 } # Execute paramater. exec "$@" if [[ $DO_BACKUP == "true" ]]; then exec /backup.sh exit 0 fi # Infinity roop. while : ; do sleep 1 ; done
実行権を付けておく。
$ chmod +x entrypoint.sh
backup.sh
Samba ad dcのバックアップは、本来ならばsamba-toolコマンドを使うべき。
今回は、ある日ある時に戻れれば良い、という割り切りバックアップ。
tarボールの連結については、ここで教えてくれたやり方で実施。
連結前と連結後をそれぞれ展開し、diffを取ってみたところ、差分はなかった。
Stack Overflow / BusyBox tar: append workaround given limited disk space?
実行すると、Sambaのディレクトリにあるソケットを圧縮しようとしてワーニングが表示される。
Alpineのtarには、ワーニングの出力を止めるオプションがなかったので、そのままにしている。
~/hd-backup/backup.sh
#!/bin/ash # Create backup files. TMP_TARGET=/mnt/backups/backup-$(hostname)-$(date +'%Y-%m-%d-%H-%M-%S').tar echo $TMP_TARGET # # Samba # echo "Samba" # make NTACL file. cd /var/lib/samba find ./sysvol -exec ash -c 'TMP=$(samba-tool ntacl get "{}" --as-sddl); echo "samba-tool ntacl set \"$TMP\" \"{}\""' \; > NTACL # make tarball. cd / tar -cvf $TMP_TARGET.1 \ etc/samba etc/bind \ var/lib/samba/private var/lib/samba/sysvol var/lib/samba/NTACL var/lib/samba/bind-dns \ var/lib/bind \ var/lib/ldap-account-manager rm var/lib/samba/NTACL # # Kopano # echo "Kopano" cd /tmp tar -cvf $TMP_TARGET.2 \ kopano/var/lib/kopano/attachments \ kopano/var/lib/mysql # # Gitea # echo "Gitea" cd /tmp tar -cvf $TMP_TARGET.3 \ gitea/data \ gitea/var/lib/mysql # # merge tarball. # echo "Merge" head -c -$((512*2)) $TMP_TARGET.1 > $TMP_TARGET head -c -$((512*2)) $TMP_TARGET.2 >> $TMP_TARGET head -c -$((512*2)) $TMP_TARGET.3 >> $TMP_TARGET rm $TMP_TARGET.1 $TMP_TARGET.2 $TMP_TARGET.3 echo "Archive" gzip $TMP_TARGET # Finish. echo "Backed up."
バックアップを実行
バックアップスクリプトは、バックアップ対象のコンテナが止まっている前提で書いた。
そこで、バックアップ対象のコンテナを止めてバックアップを実行し、その後にコンテナを起動するスクリプトを作った。
~/hd-backup/do-backup.sh
#!/bin/bash cd $(dirname ${0}) docker container stop gitea gitea_db kopano kopano_db samba docker compose up --build #docker compose down docker container start samba kopano_db kopano gitea_db gitea
バックアップ対象のSambaやKopano、Giteaのコンテナを手でメンテナンスしている時に、ミスでボリュームが消えたら大変。
今回、バックアップ対象のボリュームを削除できなくするのを目的の1つにしているので、ここではあえてbackupコンテナを削除しないことにした。
これにより「参照しているコンテナがいる」状態になるので、ボリュームを削除できない。
このスクリプトを実行。
cornに登録しておけば、忘れずにやってくれるだろう。
$ sudo ./do-backup.sh
雑すぎるけれども、ホームラボではこれくらいで十分。
場所や状況によっては、この程度のバックアップでも良いかもしれない。
リストア
リストアは、コンテナを起動したあと中に入ってやるつもり。
コンテナを起動する前に、環境変数を変更する。
~/hd-backup/docker-compose.yml
…
backup:
…
environment:
TZ: Asia/Tokyo
DO_BACKUP: "false"
…
コンテナを起動して、コンテナの中に入る。
$ sudo docker compose up -d $ sudo docker exec -it backup ash --login
バックアップファイルは、以下に置かれている。
# ls -la /mnt/backups/backup-$(hostname)* -rw-r--r-- 1 root root 94364577 Sep 21 00:01 /mnt/backups/backup-hogedomain-2022-09-20-15-00-45.tar.gz -rw-r--r-- 1 root root 94735800 Sep 21 23:38 /mnt/backups/backup-hogedomain-2022-09-21-14-37-48.tar.gz -rw-r--r-- 1 root root 103409960 Sep 26 21:28 /mnt/backups/backup-hogedomain-2022-09-26-12-28-11.tar.gz -rw-r--r-- 1 root root 107503016 Oct 9 05:19 /mnt/backups/backup-hogedomain-2022-10-09-05-19-21.tar.gz
展開して、しかるべき場所にファイルを復元する。
# cd /mnt # tar zxvf backups/backup-hogedomain-2022-10-09-05-19-21.tar.gz
バックアップの中に、以下のファイルがある。
var/lib/samba/NTACL
samba-tool ntacl set "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)" "./sysvol" samba-tool ntacl set "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)" "./sysvol/hogeserver.hogeddns.jp" …
これは、バックアップを作成した際に、Samba ad dcで拡張属性を取り出して、リストア用の設定スクリプトにしたもの。
ファイルを展開しただけでは拡張属性が復元できないので、しかるべき場所に復元したら、var/lib/samba相当のディレクトリに移動して、スクリプトを実行する。
そして、NTACLファイルは、実行後削除する。
さいごに
Nextcloud all in one を試した時に、周りのコンテナを起動したり停止したりしていた。
今回のコンテナでそれができれば、もう少しきめ細やかなバックアップができるようになるので、どうやっているのか知りたいなぁ。
コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他