ブログ
Dockerコンテナ内のDBを外部から定期バックアップする
最近、Dockerコンテナ外(ホスト側)からコンテナ内DBのバックアップを取れるようにしたので、その方法などを備忘録として書きたいと思います。
環境
- macOS Catalina 10.15.7
- Docker Desktop for Mac
- MySQL 8.0
ふと、Docker開発環境のDBを定期的にバックアップしたいと思いました。
定期実行と言うとcronが思い浮かびましたが、DBコンテナにcronは入っていません。
あくまで個人的に導入するものなので、なるべくDockerの設定を触らずに実現することを前提に、ホスト側のcronでmysqldumpを取るバッチを動かすという方法を試してみました。
バッチファイル作成
まずはホスト側にフォルダ・ファイルを用意します。
任意のフォルダ/
├ backup_local_db.sh # 実行ファイル
├ conf.txt # 設定ファイル
└ mysqldump_user.conf # MySQL設定ファイル
backup_dump/ # dump出力先フォルダ
#!/bin/bash
CURRENT_DIR=`cd $(dirname $0) && pwd`
source ${CURRENT_DIR}/conf.txt
echo `date '+%Y/%m/%d %T'`" START backup_local_db"
# DBコンテナ起動確認
container_id=`docker ps -q -f status=running -f name=${CONTAINER_NAME}`
if [ -z "$container_id" ]; then
echo "$CONTAINER_NAME is not running"
exit 0
fi
# バックアップフォルダの作成
if [ ! -e BACK_DIR ]; then
mkdir -p ${BACK_DIR};
fi
# DBバックアップ
dump_name=${DB_NAME}_`date "+%Y%m%d"`.sql
docker exec ${CONTAINER_NAME} mysqldump --defaults-extra-file=${DEF_FILE} ${DB_NAME} ${DUMP_OPTION} > ${BACK_DIR}/${dump_name}
# 5日より古いファイルを削除
find ${BACK_DIR} -type f -name "${DB_NAME}_*.sql" -mtime +5 | xargs rm -f;
echo " "${dump_name}
echo `date '+%Y/%m/%d %T'`" END backup_local_db"
PATH=/bin:/usr/bin:/usr/local/bin:$PATH
BACK_DIR=dump出力先フォルダ(backup_dump)をホスト側から見たフルパスで記述
CONTAINER_NAME=コンテナ名
DEF_FILE=MySQL設定ファイル(mysqldump_user.conf)をコンテナ側から見たフルパスで記述
DB_NAME=DB名
DUMP_OPTION="--skip-lock-tables --single-transaction"
[mysqldump]
user=MySQLユーザ名
password=MySQLパスワード
docker exec コンテナ名 mysqldump
でコンテナに入らなくてもmysqldumpを取ることができます。
実行ファイルについてはほとんどコメントで書いている通りですが、いくつかハマったポイントがあるので後述します。
設定ファイルのフォルダ・ファイルの指定はどこから見たフルパスなのか気を付ける必要があります。
dump出力先フォルダはホストのcronから見る場所なのでホスト側のフルパス、MySQL設定ファイルはコンテナ内のMySQLが見るものなのでコンテナ側のフルパスとなります。
MySQL設定ファイルは、以下のようにコマンドラインからパスワードを使用した際の警告メッセージが出ないようするために作成しています。
# mysql -uroot -pPassword -h localhost
mysql: [Warning] Using a password on the command line interface can be insecure.
cron設定
あとはターミナルからホストのcronを設定します。
私は月〜金の15時に起動しています。
% crontab -l
# mysqldump
00 15 * * 1-5 /Users/(省略)/backup_local_db.sh > /Users/(省略)/backup_local_db.log
ハマったポイント
ターミナル.appの権限設定
ターミナルからcronの保存時に以下のようなメッセージが表示されました。
OKを押せば設定はできるのですが、いちいち出てくるのも煩わしいのでターミナルにフルディスクアクセス権限を与えるように設定しました。(※)
システム環境設定>セキュリティーとプライバシー>プライバシータブ
フルディスクアクセスにターミナル.appを追加するとメッセージは出なくなります。
※ フルディスクアクセス権限を付与すると、ターミナルから全てのディレクトリへのアクセスが許可されます。
セキュリティ的に好ましくない場合もありますので、必要な場合のみ行うことをおすすめします。
macOSでのアプリケーションからファイルへのアクセスの制御
docker exec
に-it
はいらない
docker exec -it ...
というコマンドはよく使うと思います。
cronから実行する際にはdocker exec
に-it
をつけるとうまくいきません。
cronでの実行時は「-i:標準入力との接続」「-t:TTYの割り当て」が必要ないからだそうです。
cronのPATHを通す
shellをコマンドラインから直接実行するとうまくいくのに、cronから実行するとファイルは出力されても中身が空、という状態に陥ってしまい悩まされました…。
cronにPATHを通す必要がありました。
必要なコマンドの場所を確認(which docker
など)して、設定ファイルにPATHを追加することで無事動きました。
PATH=/bin:/usr/bin:/usr/local/bin:$PATH
まとめ
コンテナ外からバッチでのDB操作方法についてご紹介しました。
Dockerについてはまだまだ知らないことがたくさんあるので、もっとスマートな方法があるかもしれません。
今後も気になったことは試していきたいと思います💪
株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問い合わせ下さい!