Help us understand the problem. What is going on with this article?

ClockworkとDockerでRubyスクリプトの定期実行

More than 1 year has passed since last update.

これは何?

  • Ruby を定期実行したい!
  • Ruby には定期実行が簡単に実行できる Clockwork がある!
  • Docker を使ってもっともっと簡単に実行できるようにしたい!(cron を導入したりとか面倒なこともしたくない)

ということでしてみましたのでそのご紹介と知見共有です

Clockworkとは

Ruby の定期実行用 Gem
定期実行といえば cron が有名であり、さらに Ruby で定期実行となれば whenever が有名かと思います。
Clockwork を使えば上記のツールを使うように簡単に定期実行を行う事ができます。

細かな話は以下のような記事や上記の公式ドキュメントをご確認ください

試してみる

上記のリポジトリに確認できるコードを置いています。自由に使ってください。
※もちろん Docker の環境が必要です

1.ソースコードのクローン

上記ソースコード一式を clone してきてください

git clone https://gitlab.com/sample-by-toririn/clockwork_docker.git

2.イメージの作成

以下のコマンドで Docker Image を作成してください

docker build -t clock_test .

3.コンテナの作成

以下のコマンドでコンテナを作成してください

docker run --name clock_test -v `pwd`:/usr/src/app -d clock_test

4.ログの確認

以下のコマンドでログを確認してください

docker logs -f clock_test

以下のようなログが次々と出て入れば無事定期実行が動いています

I, [2019-08-10T00:52:35.005344 #1]  INFO -- : Triggering 'test'
2019年08月10日の00時52分35秒だよ!
I, [2019-08-10T00:52:35.005344 #1]  INFO -- : Triggering 'test'
2019年08月10日の00時52分38秒だよ!

※時間は実行した時間が表示されるかと思います

5.ちょっとした修正

コンテナ作成時に -v オプションをつけていたので直接コードを修正してください。
修正ができればコンテナを再起動することで反映がされます

docker restart clock_test

仕組み

仕組みというほどのことはありませんが、単純に Ruby の公式イメージに Clockwork をインストールし実行をしているだけです。

Dockerfile

以下が Dockerfile です

FROM ruby:2.6.3-slim-stretch
ENV LANG C.UTF-8
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN bundle install

CMD ["bundle", "exec", "clockwork", "config/clock.rb"]

5行目でイメージを作成するときにソースコード一式をイメージに入れています。
6行目で clockwork のインストールを行なっています
最後にコマンドで clockwork を実行しています

config/clock.rb

以下が clockwork の設定ファイルです(一部省略)

# 定期実行で利用するクラスの読み込み
require_relative '../lib/clock_test'

# Clockworkを利用するためにモジュールを読み込み
include Clockwork
# 定期実行で利用するクラスの読み込み
include ClockTest

# Clockworkの設定値
configure do |config|
  # 日本時間のタイムゾーンを設定
  config[:tz] = "Asia/Tokyo"
end

# ...省略

# 3秒に1回実行
every(3.seconds, "test") do
  Foo.new.run
end

説明は書いている通りです。
clockwork の設定側でタイムゾーンに日本時間を設定しています。こちらがなければ UTC で実行されることになります。
この設定もなくしたければ Docker Image のシステム時間を日本時間に変更することでも対応できます

ログで確認できたのは3秒に1回実行される設定をしていたところです

Foo.new.run

以下が Foo クラスの中身です

require_relative "logger"
module ClockTest
  class Foo
    def run
      current_time = Time.new.strftime("%Y年%m月%d日の%H時%M分%S秒だよ!")
      Logger.info(current_time)
    end
  end
end

ただ現在時刻をとってきてログに出しているだけです。

しかし DockerRubyTime クラスを使うのには注意が必要です

Ruby が利用するタイムゾーンを設定する

以下が設定を行なっている initialize.rb の中身です

require "time"
# 時間を日本時間にする
ENV["TZ"] = "Asia/Tokyo"

RubyTZ という環境変数にタイムゾーンの地域を設定していれば、そのタイムゾーンを使ってくれます。
もし上記の設定がなければシステムのタイムゾーンが使われます。

だいたいのピュアな Docker ImageUTC になっているので、上記の設定を追加して日本時間のタイムゾーンを設定しています。

これで Time.new で取得される時刻オブジェクトは日本時間のものになりました。

補足

ここで設定しなくても DockerfileENV の設定を記載することでも日本時間に変更することは可能です!

参考: Rubyのタイムゾーン

まとめ

  • Docker + Ruby で定期実行処理はとても簡単にできる
lassic
ITを駆使して地方を元気にする株式会社LASSIC(ラシック)。地方を舞台に自分らしく働く優秀な技術者が、貴社のWEB・スマートフォンサイトやアプリ開発、システム開発プロジェクトを成功へと導きます。~鳥取発~ITで地方創生
https://www.lassic.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした