mysqlのバックアップ用rakeタスクを作成する
ここを参考にしながら、mysqlデータベースをaws s3にバックアップを行なうためのrakeタスクを書いた。そしてそれをwheneverで定期的に実行するようにしてデータベースのバックアップ体制を取りました。ここのスクリプトでは、dotenvとaws-sdkに依存しています。dotenvを使用している部分はよしなに環境変数を使用するように変更すると良いと思います。
Railsでデータベースのバックアップを取るためのgemとしてbackupっていうgemもあるのですが、設定が色々と面倒くさそうだったので、ミニマムに自分で書いた方が早そうだと思って自分でスクリプト書く次第となりました。
とりあえずで書いたので、DRYになってないのでリファクタリング掛けたい所。
require 'dotenv/tasks'
namespace :backup do
desc "nightly backup"
task :nightly => :dotenv do
timestamp = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
backup_file = "tmp/backups/#{timestamp}_dump.sql.gz"
`mkdir -p tmp/backups`
`mysqldump -u #{ENV['DB_USERNAME']} -p#{ENV['DB_PASSWORD']} #{ENV['DB_NAME']} | gzip -c > #{backup_file}`
send_to_s3_nightly backup_file
end
desc "weekly backup"
task :weekly => :dotenv do
timestamp = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
backup_file = "tmp/backups/#{timestamp}_dump.sql.gz"
`mkdir -p tmp/backups`
`mysqldump -u #{ENV['DB_USERNAME']} -p#{ENV['DB_PASSWORD']} #{ENV['DB_NAME']} | gzip -c > #{backup_file}`
send_to_s3_weekly backup_file
delete_olds
end
def delete_olds(num = 10)
bucket = get_bucket
bucket.objects.with_prefix("backups/nightly/").each do |backup|
datestr = backup.key.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}/)[0]
date = DateTime.strptime(datestr,"%Y-%m-%d_%H-%M-%S")
if (Date.today - num).to_datetime > date
backup.delete
end
end
bucket.objects.with_prefix("backups/weekly/").each do |backup|
datestr = backup.key.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}/)[0]
date = DateTime.strptime(datestr,"%Y-%m-%d_%H-%M-%S")
if (Date.today - num * 7).to_datetime > date
backup.delete
end
end
end
def send_to_s3_nightly(file_path)
bucket = get_bucket
file_name = File.basename(file_path)
bucket.objects["backups/nightly/#{file_name}"].write(File.open("#{file_path}"))
end
def send_to_s3_weekly(file_path)
bucket = get_bucket
file_name = File.basename(file_path)
bucket.objects["backups/weekly/#{file_name}"].write(File.open("#{file_path}"))
end
def get_bucket
s3 = AWS::S3.new(
access_key_id: ENV["AWS_ACCESS_KEY_ID"],
secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
s3_endpoint: ENV['S3_HOST_NAME']
)
bucket = s3.buckets[ENV['S3_BUCKET_NAME']]
bucket = s3.buckets.create(ENV['S3_BUCKET_NAME']) unless bucket.exists?
bucket
end
end
wheneverで定期的に実行する
先ほど書いたrakeタスクをwheneverで毎日、毎週走らせます。こちらを参考に導入しましたが、導入が簡単で良いですね。
まずは、wheneverをGemfileに追加
+ gem 'whenever', :require => false
wheneverの設定ファイルを生成するコマンドが付いてくるので、実行します。
cd path/to/project_dir/
wheneverize .
先ほど生成された設定ファイルconfig/schedule.rb
に設定を書いて行きます。capistranoと連携させるために、roleを記述しています。
# 出力先のログファイルの指定
set :output, 'log/crontab.log'
# ジョブの実行環境の指定
set :environment, :production
# 毎日 am4:30のスケジューリング
every 1.day, :at => '4:30 am', :roles => [:db] do
rake "backup:nightly"
end
# 日曜日のpm12時にスケジューリング
every :monday, :at => '4am', :roles => [:db] do
rake "backup:weekly"
end
capistrano v3でデプロイ時にwheneverを設定するようにする
+require "whenever/capistrano"
+SSHKit.config.command_map[:whenever] = "bundle exec whenever"
set :whenever_environment, "#{fetch(:stage)}" #wheneverでの環境指定に必要
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" } #cronjobのユニークを保つために必要
これで、デプロイの設定は終了。あとは
bundle exec cap production deploy
すれば、自動でwheneverの設定を反映させてくれます。