設定手順(Dockerを考慮しない場合)
Gemfileにwheneverを追加
gem 'whenever', require: false
bundler install
bundle install
configファイル配下にschedule.rbを追加
schedule.rbを編集
#出力先ログ
set :output, 'log/cron_monthly_batch.log'
#実行環境
set :environment, :development
#実行日時
every '0 0 1 * *' do
runner '~'
rake '~'
end
scheduleをcronにセット
bundle exec whenever --update-crontab
■設定後の操作
cronにscheduleが設定されているか確認
crontab -l
cronからscheduleを削除
bundle exec whenever --clear-crontab
or
crontab -r(※全タスク削除)
crontab -e(※任意のタスク削除)
Dockerでcronを設定したい場合
■前提
- Dockerコンテナでdaemonは標準で自動起動しない
- なので、明示的にcronを動かすための設定をする必要がある
- しかしながら、1機能1コンテナというdocker管理の基本的な考えに従うならば、既存のコンテナにcrobジョブを動かすための設定を追加するのはベストプラクティスではない
- 上記を踏まえると、大きな方針は以下になる。
- デプロイ対象がEC2であることを前提にするならば、cron専用のdockerコンテナを新規で切り出すのが望ましい。
- デプロイ対象がFargateであることを前提するにするならば、ECSタスク経由でcronに相当するjobをAWSのサービスを利用して動かす。
■Cron用の新規Dockerコンテナを作成する場合の実装例
docker-compose.ymlに以下を追記(※cron用コンテナの作成)
cron:
<<: *サービス名
depends_on:
- 基礎となるコンテナ名
command:
- bash
- -c
- |
bundle exec whenever --update-crontab
cron -f
Dockerfile内gemインストールリストにcronを追加
UN apt install -y --no-install-recommends \
git \
vim \
cron
configファイル配下にschedule.rbを追加
schedule.rbを編集
# Rails.rootを使用するようにする(※wheneverはrailsの起動を前提とするため)
require File.expand_path(File.dirname(__FILE__) + "/environment")
# コンテナ起動時の環境変数をcron独自の環境変数にパス
ENV.each { |k, v| env(k, v) }
#出力先ログ
set :output, 'log/cron_monthly_batch.log'
#実行環境
set :environment, :development
#実行日時
every '0 0 1 * *' do
runner '~'
rake '~'
end
schedule.rbで呼び出したいメソッドがlibディレクトリ配下にない場合どうするか
■rakeタスクでない場合(=メソッドの直接呼び出し)
app/util/tasks配下
require "#{Rails.root}/app/models/test_class.rb"
class Tasks::MonthlyBatch
def self.monthlyjob
TestClass.new.test_batch_method(Date.today)
end
end
config/schedule.rb
every 5.minutes do
runner 'Tasks::MonthlyBatch.monthlyjob'
end
■rakeタスクの場合
app/util/tasks配下
namespace :batch do
desc "generate records"
task generate: :environment do
TestClass.new.test_batch_method(Date.today)
end
end
config/schedule.rb
every 5.minutes do
rake 'batch:generate'
end