🐡
【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設定もラクラクですね。ぜひお試しください〜!
Discussion