lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

dockerのmysqldbからテーブル毎のmysqldump&リストア

概要

ローカル環境にて稼働するDockerのDB(MySQL)から全テーブル、全データのdumpを取得するシェルと
取得したdumpデータを全リストアするシェルです。

シェルを1本したためてコンテナに配置すればいいものを、
dockerコマンドのワンライナーで書いてしまった...
無駄に時間がかかりました。

目次

前提&補足

シェルの中で登場する、パスについて

ローカル側のdataディレクトリとDockerコンテナ側の/bkupディレクトリは
volumesでマウントされている前提です。

成果物

dockerのmysqlからmysqldumpとデータリストアが出来るシェル · GitHub

mysqldumpのシェル

下記から抜粋

dockerのmysqlからmysqldumpとデータリストアが出来るシェル · GitHub

dump() {
  echo "mysqldump start"
  docker exec -i dbcontainer sh -c "(echo 'show tables' | MYSQL_PWD=password mysql -u testuser testdb | sed -e '1d' > /bkup/all_tables.txt;)"
  docker exec -i dbcontainer sh -c "(while read line; do echo \$line; MYSQL_PWD=password mysqldump -u testuser testdb \$line --opt | sed '/^-- Dump completed on/d' > /bkup/\$line.sql; done < /bkup/all_tables.txt;)"

  if [ $? != 0 ]; then
      echo "mysqldump failed"
      exit 1
  fi
  echo "mysqldump end"
}

1つ目のdockerコマンドでテーブル一覧を取得
(dumpしたデータをテーブル毎に管理したかったから。) 2つ目のdockerコマンドでテーブル一覧を元にテーブル毎のdumpを取得って形の処理です。

ワンライナーでよくわからないので詳細を見ていきます。

テーブル一覧の取得

下記のワンライナーです。

docker exec -i dbcontainer sh -c "(echo 'show tables' | MYSQL_PWD=password mysql -u testuser testdb | sed -e '1d' > /bkup/all_tables.txt;)"

詳細を見ていきます。

echo 'show tables' | MYSQL_PWD=password mysql -u testuser testdb | sed -e '1d' > /bkup/all_tables.txt;

mysqlshow tablesコマンドをmysqlコマンドに渡してテーブル一覧を取得します。
取得したテーブル一覧の1行目にカラム名が入っていて邪魔なのでsedコマンドで1行目を消しています。

テーブル毎のdumpデータ取得

下記のワンライナーです。 前述のテーブル一覧を元にテーブル毎のdumpデータを取得します。

docker exec -i dbcontainer sh -c "(while read line; do echo \$line; MYSQL_PWD=password mysqldump -u testuser testdb \$line --opt | sed '/^-- Dump completed on/d' > /bkup/\$line.sql; done < /bkup/all_tables.txt;)"

詳細を見ていきます。(少し整形しました。)

while read line;
do
    echo \$line
    MYSQL_PWD=password mysqldump -u testuser testdb \$line --opt | sed '/^-- Dump completed on/d' > /bkup/\$line.sql
done < /bkup/all_tables.txt;

whileで先程取得したテーブル一覧を流し込んでmysqldumpコマンドに喰わせています。
今回はgit管理したかったのですが、timestampが差分で毎回出て邪魔だったので、
sedコマンドでtimestamp部分のみ消しています。

詰まりポイント:$エスケープ

dockerコンテナ内で変数を使うには$マークのエスケープが必要だったようでどん詰まりしました。

リストアのシェル

下記から抜粋

dockerのmysqlからmysqldumpとデータリストアが出来るシェル · GitHub

restore() {
  echo "data restore start"

  for file in data/*.sql
  do
      echo "$file"
      docker exec -i dbcontainer sh -c "MYSQL_PWD=password mysql -u testuser testdb" < "$file"
  done

  if [ $? != 0 ]; then
      echo "data restore failed"
      exit 1
  fi
  echo "data restore end"
}

特に難しいことはしていません。
取得したダンプデータをdockerのDBに流し込んています。
ただ、それだけ。

以上

雑感

マジでドルマークのエスケープでハマった。