なんとコンテナ内のデータを、コンテナの外のディレクトリにバックアップすることができる!!
すげえ!
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
これらのサイトに書いてた。
また、バックアップファイルに日時の情報を含めたければ、
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】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にコードを貼り付けることもできる。
全選択して削除した後に貼り付ける場合は、以下の記事を参考にして!
作成したら忘れずに
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
を叩く。
失敗したときにメールを飛ばすには?
まずは成功含め飛ばしてもいい。
メールサーバーは立てる必要があるのか。
この辺はまた別でまとめる必要がありそう。