なんとコンテナ内のデータを、コンテナの外のディレクトリにバックアップすることができる!!

すげえ!

Docker Compose データベースのバックアップとリストア方法 - Qiita

この記事を見ながらやっていく

まずは、下記のコマンドでDockerのdbコンテナに入りつつログインまですることができるかを確認。

docker compose exec db bash -c 'mysql -u mysqlのユーザー名 -p MySQLのパスワード MySQLのデータベース名'

今回環境変数は使わずに、コマンド直打ちで行ってみる。

具体的な設定値は、Laravelなら.envから拾える

mysqlのユーザー名:DB_USERNAMEのやつ

MySQLのパスワード:DB_PASSWORD

MySQLのデータベース名:DB_DATABASE

自分の環境だと下記から拾い上げるので、

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:n6p03pNflB5QkVg/WEYl9YwI2ah+NG05kEF/Xts1vjg=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_local
DB_USERNAME=phppikumin
DB_PASSWORD=secreton

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=43800

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

下記のコマンドをコンテナの外(プロジェクトディレクトリ)でたたくとことになる。

docker compose exec db bash -c 'mysql -u phppikumin -psecreton laravel_local'

docker-compose exec db bash -c 'mysql -u phppikumin -psecreton laravel_local'

ちなみにお手本のサイトの記事は末尾のクオーテーションが全角かなんかになって間違っているから注意。

入れることが確認できたらOK.

\\q

って打ったら抜けれる。

バックアップ方法

docker compose exec db bash -c 'mysqldump --no-tablespaces -u phppikumin -psecreton laravel_local > /tmp/dump.sql'

docker-compose exec db bash -c 'mysqldump --no-tablespaces -u phppikumin -psecreton laravel_local > /tmp/dump.sql'

を叩いて、コンテナ内のsqlの情報をコンテナ内のtmpディレクトリ内にdump.sqlって名前で保存する。

ほいだらCtrl + Cでコンテナから出る。

続けてコンテナ内のファイルを、リアルフォルダにコピーする。

docker compose cp db:/tmp/dump.sql /tmp/dump.sql

docker-compose cp db:/tmp/dump.sql /tmp/dump.sql

みたいに叩けば、バックアップが実機のtmpディレクトリ直下に作成される。

MAC環境なら、Macintosh HD/private/tmp にdump.sql

というバックアップファイルが作成される。

この場合、同じコマンドをもう一度叩くと上書きされるっぽい。

ただし、docker compose cpが使えない事情があるのであれば

docker cp `docker-compose ps -q db`:/tmp/dump.sql /バックアップ先のリアルフォルダ/dump.sql

みたいなコマンドになる。

自分の環境ではこんな感じ。

docker cp `docker-compose ps -q db`:/tmp/dump.sql /root/backup/dump.sql
docker cp `docker-compose ps -q db`:/tmp/dump.sql /tmp/dump.sql

これらのサイトに書いてた。

https://qiita.com/reflet/items/ad734edc87c73cbaa459https://hirokts.hatenablog.jp/entry/2018/03/22/141228

また、バックアップファイルに日時の情報を含めたければ、

docker cp `docker-compose ps -q db`:/tmp/dump.sql /tmp/backup_`date +%Y%m%d%H%M`.sql

日付をファイル名に含む状態でバックアップできるように本番環境のサーバーにcrontabとかで組めばいいと思う。

もちろん定期的に削除する処理も必要。

消すためのジョブ作成方法は、まだ試してないけどこのサイトが使えそう。

https://itneko.com/linux-delete-old-file/

find ${対象ディレクトリ} -type f -ctime +7 | xargs rm

なんてわかりにくい書き方してるけど、対象ディレクトリを変数で表すならこんな記述になるよってゆうてるだけ。

リストア方法

phpmyadminにログイン

インポートからバックアップファイルを選んで実行するだけ。

これだけでうまくいった。

phpMyAdminのインポート上限値に引っかかる場合

1024KBまでしかインポートできないのがデフォルトの仕様。

変更が必要なら下記参照。
Docker環境におけるphpMyAdminの最大インポートサイズを変更方法

コマンドラインで復元するなら?

コマンドで復元するやり方はお手本のサイト通りではうまくいかなかった。

もしコマンドでやるなら
docker exec -i コンテナ名 mysql -uデータベースユーザー名 -データベースパスワード データベース名 < バックアップファイル.sql
でできる。

詳しくは下記の記事まとめている。
Docker MySQLコンテナでコマンドラインからsqlインポート方法

自動バックアップ

定期バックアップするのであれば、ジョブを組もう。

外付けUSBデバイスのマウント

外付けUSBデバイスにバックアップするなら下記の記事を参考にあらかじめUSBメモリをマウントする必要がある。

マウント方法はこの記事を参照。

ubuntuに外付けUSBメモリをマウントする方法

シェルスクリプトの作成

このサイトがわかりやすいので参考にしていく。

【Ubuntu】cron(crontab)でプログラムを定期的に実行:ジョブスケジューリング | OFFICE54

バックアップの一連の動作を行うシェルスクリプトを作成する。

vim /usr/local/bin/database-backup.sh

#!/bin/bash
projectDirectory=/root/crm-app
backupDirectory=/root/backup

#バックアップ
cd ${projectDirectory}
/usr/bin/docker-compose exec db bash -c 'mysqldump --no-tablespaces -u phppikumin -psecreton laravel_local > /tmp/dump.sql'
/usr/bin/docker cp `docker-compose ps -q db`:/tmp/dump.sql ${backupDirectory}/backup_`date +%Y%m%d%H%M`.sql

#古いファイルを削除
find ${backupDirectory} -type f -name "*backup*"  -ctime +7 | xargs rm

一応、バックアップ先は外付けUSBメモリをマウントしたフォルダにしてる。

docker-composeやdockerコマンドはフルパスで書いてあげないとなんかファイルが更新されない。

本例では、/root/crm-appというプロジェクトディレクトリでバックアップのコマンドを実行し、

/root/backupにバックアップファイルを保存する

という流れになっている。

まだ古いファイルを削除する挙動は動作確認できてない。

vimで書きにくければ、手元のエディターで編集し、その後vimにコードを貼り付けることもできる。

全選択して削除した後に貼り付ける場合は、以下の記事を参考にして!

vimで全選択削除する方法

作成したら忘れずに

chmod 755 /usr/local/bin/database-backup.sh

を叩いて、一応ルート権限以外からも実行できるようにする。

/bin/bash /usr/local/bin/database-backup.sh

を叩いて、バックアップファイルが任意のディレクトリに正常に生成されたらコマンド自体は正しいことになる。

定期的にシェルスクリプトを呼び出す設定

vim /etc/cron.d/ubuntu

1分前くらいにバックアップを取る場合

*       *       *       *       *       root    /bin/bash /usr/local/bin/database-backup.sh

毎時21時になったらバックアップを取る場合

00      21       *       *       *       root    /bin/bash /usr/local/bin/database-backup.sh

詳しいスケジュールの組み方は

https://www.server-memo.net/tips/etc-crontab.html#i-3

このサイトがわかりやすい。

ポイントは

  • コマンドを実行するユーザーを指定しなければいけない
  • /bin/bashを使うことを宣言する

みたいな感じ。

基本実行ユーザーはrootでいいと思うが、

もしコマンド直打ちは通るのにcronだと実行されないならwhoamiコマンドで実行可能なユーザー名を調べてみるといい。

root@yaju-OptiPlex-3020:~/backup# whoami
root

自分の場合は普通にrootだった。

時間が来ても走らない場合

service cron status

を叩いたときに

cron is running

ってなってなかったらそもそもcronが止まっているので、

service cron restart

を叩く。

失敗したときにメールを飛ばすには?

まずは成功含め飛ばしてもいい。

メールサーバーは立てる必要があるのか。

この辺はまた別でまとめる必要がありそう。

参考にしたサイト

Docker Compose データベースのバックアップとリストア方法 - Qiita

日時をファイル名に付けるには

無制限に質問可能なプログラミングスクール!

万が一転職できない場合は、転職保障全額返金できるコースもあり!!

無制限のメンター質問対応

 

DMMウェブキャンプでプログラミングを学習しませんか?

独学より成長スピードをブーストさせましょう!

 

まずは無料相談から!

おすすめの記事