動機
Railsの定期実行を行うwhenever
を使おうとしたのですが、Mac上で直接実装すると環境変数や権限管理で大変だったのでdockerで行うことにしました
前提条件
実行環境は下記のようになります
・ ruby 2.6.3
・ Rails 5.2.4
・ MySQL 8.0.19
Docker関係
Dockfile
、docker-compose.yml
は以下のようになります
通常のdockerの設定とあまり変わらないのですが、今回はwheneverを利用するのでcorn
のインストールとcronをフォアグラウンド実行するための設定を追記しています。
FROM ruby:2.6.3
# rubyのバージョン指定
# gemのインストール
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs
# cronインストール
RUN apt-get install -y cron
RUN mkdir /my_app
WORKDIR /my_app
COPY Gemfile /my_app/Gemfile
COPY Gemfile.lock /my_app/Gemfile.lock
RUN gem install bundler
RUN bundle install
COPY . /my_app
# wheneverでcrontab書き込み
RUN bundle exec whenever --update-crontab
# cronをフォアグラウンド実行
CMD ["cron", "-f"]
docker-compose.yml
version: '2'
services:
db:
image: mysql:8.0.19
command:
--default-authentication-plugin=mysql_native_password
volumes:
- ./mysql-confd:/etc/mysql/conf.d
- mysql-data:/var/lib/mysql #データの永続化のため
ports:
- "3306:3306"
restart: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 1
# MYSQL_DATABASE: app_development
MYSQL_USER: root
# MYSQL_PASSWORD: password
TZ: Asia/Tokyo
app:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/my_app
- bundle:/usr/local/bundle
ports:
- "3000:3000"
links:
- db
volumes:
mysql-data:
bundle: #bundle installした後buildし直さなくてよくなる
whenever関係
config/schedule.rb
# wheneverにrailsを起動する必要があるためRails.rootを使用
require File.expand_path(File.dirname(__FILE__) + "/environment")
# 環境変数をうまい感じにやってくれる
ENV.each { |k, v| env(k, v) }
# ログを書き出すようファイル
set :output, error: 'log/crontab_error.log', standard: 'log/crontab.log'
set :environment, :development
# 2分毎に`sample_task`の`scheduled_task`を実行する
every 2.minutes do
rake 'sample_task:scheduled_task'
# runner "Test.yakisoba", :environment => :development # runnnerの例
end
実行したいコマンド
/lib/tasks/sample_task.rb
namespace :sample_task
desc "scheduled_task"
task scheduled_task: :environment do
..... 実行したい関数
end
end
end