1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Docker ComposeでMySQLの定期バックアップ

Posted at

Docker Composeで構成したMySQLコンテナのデータベースの内容を定期的にバックアップする方法。

databack/mysql-backupというDockerイメージがあったのでこれを使う。

定期バックアップ

docker-compose.yaml
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_SERVERDB_USERDB_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になっており、このユーザがマウントしたバックアップの出力ディレクトリに書き込めるようにディレクトリのパーミッションを設定しておかねばならない。

古いバックアップファイルの自動削除

このままだと古いバックアップファイルが無限に溜まっていくので、規定時間以上前のバックアップを自動で削除するようにする。このイメージにはバックアップ実行前もしくは後に実行するスクリプトを設定することができるので、その機能を活用する。

以下のシェルスクリプトを作成。

dbbackup/remove-old-backups.sh
#!/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/ディレクトリ内に配置することにより、バックアップ実行前に毎回実行させる。

docker-compose.yaml
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}はどこかで定義しておく。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?