Docker Composeで構成したMySQLコンテナのデータベースの内容を定期的にバックアップする方法。
databack/mysql-backupというDockerイメージがあったのでこれを使う。
定期バックアップ
services:
db:
image: mysql:8.0.27
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
volumes:
- ./db/storage:/var/lib/mysql
dbbackup:
image: databack/mysql-backup
depends_on:
- db
environment:
- DB_SERVER=db
- DB_USER=root
- DB_PASS=${MYSQL_ROOT_PASSWORD}
- DB_DUMP_FREQ=1440
- DB_DUMP_TARGET=/db
volumes:
- ./dbbackup/storage:/db
サービスdb
がMySQLコンテナ、サービスdbbackup
がバックアップを行うコンテナ。
環境変数について、DB_SERVER
、DB_USER
、DB_PASS
はそれぞれデータベースのホスト名、ユーザー名、パスワード。DB_DUMP_FREQ
はバックアップの間隔で単位は分。ここでは $1440=60\times24$ より1日間隔。DB_DUMP_TARGET
はバックアップファイルを出力するディレクトリで、volumes
でホストのディレクトリをマウントして使う。ここではホストの./dbbackup/storage
ディレクトリにバックアップされた圧縮ファイルが置かれる。
その他の設定についてはdataback/mysql-backupに詳しい解説がある。バックアップファイルをSMBのネットワークドライブ上に置いたりAWS上に置いたりもできる模様。
バックアップファイルを置くディレクトリのパーミッションについて
このDockerイメージ内のプロセスはデフォルトではroot
ではなくappuser
という名前の一般ユーザで動く。appuser
のUIDおよびGIDは共に1005
になっており、このユーザがマウントしたバックアップの出力ディレクトリに書き込めるようにディレクトリのパーミッションを設定しておかねばならない。
古いバックアップファイルの自動削除
このままだと古いバックアップファイルが無限に溜まっていくので、規定時間以上前のバックアップを自動で削除するようにする。このイメージにはバックアップ実行前もしくは後に実行するスクリプトを設定することができるので、その機能を活用する。
以下のシェルスクリプトを作成。
#!/bin/bash
# Expect to be run as a pre-backup script of databack/mysql-backup docker image.
# Remove old backup files.
find $DB_DUMP_TARGET -type f -name "db_backup_*" -mtime +14 -delete
find
コマンドで作成から(正確には最終変更から)15日=360時間 以上経ったバックアップファイルを削除している(何故か+1される)。
忘れずに実行権限を付与。
$ chmod a+x dbbackup/remove-old-backups.sh
これをコンテナ内の/scripts.d/pre-backup/
ディレクトリ内に配置することにより、バックアップ実行前に毎回実行させる。
services:
db: 同上
dbbackup:
image: databack/mysql-backup
depends_on:
- db
environment:
- DB_SERVER=db
- DB_USER=root
- DB_PASS=${MYSQL_ROOT_PASSWORD}
- DB_DUMP_FREQ=1440
- DB_DUMP_TARGET=/db
volumes:
- ./dbbackup/storage:/db
- ./dbbackup/remove-old-backups.sh:/scripts.d/pre-backup/remove-old-backups.sh:ro
最終行でスクリプトを読み込み専用でマウントすることで配置している。
リストア
バックアップしたファイルからリストアしたい場合の手順を説明する。
MySQLコンテナはDocker Composeで作られたネットワーク内にあるので、リストアする時も同じネットワークに入らなければならない。まずはそのネットワーク名をdocker network ls
で調べる。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
a9a22d4ca2c4 bridge bridge local
1616ec62a69d host host local
fe23f5a77f5a none null local
4823fecb1757 myproject_default bridge local
NAME
列がネットワーク名であり、特に指定しなければプロジェクト名(docker-compose.yaml
が配置されたの直上のディレクトリ名)の後ろに_default
が付いた名前になる模様。ここでは最終行のmyproject_default
がネットワーク名。
リストアをdocker run
コマンドで実行する。調べたネットワーク名を--network
オプションで指定し、環境変数DB_RESTORE_TARGET
にバックアップファイルを指定して実行するとそのファイルからリストアされる。
$ docker run \
--network myproject_default \
-e DB_SERVER=db -e DB_USER=root -e DB_PASS=${MYSQL_ROOT_PASSWORD} \
-e DB_RESTORE_TARGET=/backup/db_backup_2022-03-30T07:25:21Z.tgz \
-v $PWD/dbbackup/storage:/backup \
databack/mysql-backup
5行目で$PWD
を使用してカレントディレクトリに展開しているのは-v
オプションでのマウント元のディレクトリは絶対パスでしか指定できないから。変数${MYSQL_ROOT_PASSWORD}
はどこかで定義しておく。