(Dockerコンテナにおいて)wheneverでcronを設定する

By | June 3, 2022

設定手順(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