BLOG

ブログ

2021/12/17 技術系

Dockerコンテナ内のDBを外部から定期バックアップする

この記事を書いた人 F.T

最近、Dockerコンテナ外(ホスト側)からコンテナ内DBのバックアップを取れるようにしたので、その方法などを備忘録として書きたいと思います。

環境

ふと、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についてはまだまだ知らないことがたくさんあるので、もっとスマートな方法があるかもしれません。
今後も気になったことは試していきたいと思います💪



株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問合せ下さい!

アーカイブ