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 を試した時に、周りのコンテナを起動したり停止したりしていた。
今回のコンテナでそれができれば、もう少しきめ細やかなバックアップができるようになるので、どうやっているのか知りたいなぁ。


コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他