🐡

【Rails × Docker】Wheneverを使ったcronジョブ構築をサクッと解説

に公開

背景

最近、週に1回くらい動かしたい定期処理があって調べていたら、Railsでは『Whenever』っていう便利なライブラリがあることを知りました。

この記事では、そのWheneverをDocker環境で手軽に動かす方法をまとめてみました。cron初心者の方にもわかりやすく、いきたいと思います。

サンプルコードはこちらのリポジトリにありますので、よければ参考にしてください。

📌 cron・crontab・Wheneverの関係をざっくり説明!

  • cron: 決まった時間に何かをやってくれるLinuxの便利屋さん。
  • crontab: cronさんが「何を」「いつ」やるのかを書き込むメモみたいなファイル。ただしシェルスクリプトだけなので、Rubyは使えない!
  • Whenever: Rubyで気軽に書いた定期処理を、cronさん用のメモ(crontab)に翻訳してくれるRailsの便利ツール。

つまりWheneverがあると、Rubyでラクラクcron設定が書けちゃうわけです。めちゃ助かる!


📌 前提条件

  • Docker, Docker Composeはインストール済みとします。

🚩 1. Railsプロジェクト作成(APIモード・DBなしでシンプルに)

mkdir rails-cron-example && cd rails-cron-example

docker run --rm -v $(pwd):/app -w /app ruby:3.2 bash -c "gem install rails && rails new . --api --skip-active-record"

🚩 2. Docker化する

① Dockerfileを作成

FROM ruby:3.2

RUN apt-get update -qq && apt-get install -y nodejs cron

WORKDIR /app

COPY Gemfile Gemfile.lock ./
RUN bundle install

COPY . .

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh

ENTRYPOINT ["entrypoint.sh"]
CMD ["rails", "server", "-b", "0.0.0.0"]

② docker-compose.ymlを作成

version: "3"
services:
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && rails server -b 0.0.0.0"
    volumes:
      - .:/app
    ports:
      - "3000:3000"

③ entrypoint.sh(cronを起動するスクリプト)

#!/bin/bash
set -e
service cron start
exec "$@"

🚩 3. Wheneverの導入

echo "gem 'whenever', require: false" >> Gemfile

docker compose build
docker compose run --rm web bundle install

docker compose run --rm web bundle exec wheneverize .

🚩 4. cronジョブの設定

config/schedule.rbを以下のように編集します。

every 1.minute do
  runner "Rails.logger.info 'Cron task executed at: ' + Time.current.to_s"
end

🚩 5. Dockerイメージにcron設定を反映

Dockerfileに追記。

RUN bundle exec whenever --update-crontab

再ビルドします。

docker compose build

🚩 6. 動作確認してみよう!

コンテナを起動。

docker compose up

別のターミナルを開き、bashでコンテナに入ります。

docker compose exec web bash

cronジョブが登録されているか確認。

crontab -l

cronが正常に動作しているかログで確認。

tail -f log/development.log

毎分こんな感じでログが出れば成功です!

Cron task executed at: 2024-05-23 15:01:00 +0900

🚩 曜日ごとに定期実行する方法(UTC時間に注意!)

コンテナ内はデフォルトでUTC時間になっているため、実行したい日本時間から-9時間したUTCの時間を書きましょう。

例えば、日本時間の月曜0時に実行したい場合、UTCだと日曜の15時になります。

every :sunday, at: '3:00 pm' do
  runner "Rails.logger.info 'Weekly cron task executed at: ' + Time.current.to_s"
end

コンテナに入ってdateコマンドで現在のUTC時刻を確認できます。

docker compose exec web bash
date

🎉 まとめ

これでRails+Docker+Wheneverで定期処理の環境が完成です。

便利なライブラリで面倒なcron設定もラクラクですね。ぜひお試しください〜!

ispec inc.

Discussion