Fly.ioで運用しているRails 8のアプリでタスクを定期的に実行

2024/11/21に公開

はじめに

Fly.ioで運用しているRailsアプリで定期的にタスクを実行したいことがありました。Supercronicを使えばできるようなので、開発中のアプリに導入してみました。

https://fly.io/docs/blueprints/supercronic/

タスクの作成

まずはrakeコマンドで実行するタスクを作成します。

rails g task scheduled_jobs deliver_daily_activities
lib/tasks/scheduled_jobs.rb
namespace :scheduled_jobs do
  desc "Deliver daily activities"
  task deliver_daily_activities: :environment do
    # task
  end
end

タスクを実行するスケジュールの設定

Railsアプリのルートにcrontabを作成します。Fly.ioにデプロイしたマシンの時刻はUTCなので、時差の9時間を考慮して設定します。

日本時間の23:58に実行する場合、UTCで14:58を指定します。

crontab
58 14 * * * bundle exec rake scheduled_jobs:deliver_daily_activities

Supercronicのインストール

Dockerfileの最終ステージの部分を編集してSupercronicをインストールします。

Dockerfile
# Final stage for app image
FROM base

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
COPY --from=build /rails /rails


# Latest releases available at https://github.com/aptible/supercronic/releases
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.2.33/supercronic-linux-amd64 \
    SUPERCRONIC_SHA1SUM=71b0d58cc53f6bd72cf2f293e09e294b79c666d8 \
    SUPERCRONIC=supercronic-linux-amd64

RUN curl -fsSLO "$SUPERCRONIC_URL" \
    && echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - \
    && chmod +x "$SUPERCRONIC" \
    && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
    && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic

COPY crontab crontab

# Run and own only the runtime files as a non-root user for security
RUN groupadd --system --gid 1000 rails && \
    useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
    chown -R rails:rails db log storage tmp
USER 1000:1000

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start server via Thruster by default, this can be overwritten at runtime
EXPOSE 80
CMD ["./bin/thrust", "./bin/rails", "server"]

Supercronicの起動

fly.tomlの[processes]セクションを以下のように追加します。

fly.toml
app = 'sampleapp'
primary_region = 'nrt'
console_command = '/rails/bin/rails console'

[build]

[deploy]
  release_command = "./bin/rails db:prepare"

[processes]
  app = "./bin/rails server -p 8080"
  cron = "supercronic /rails/crontab"

[env]
  HTTP_PORT = '8080'

Fly.ioにアプリをデプロイします。

fly deploy

タスクを実行するマシン数を設定

自分の場合はタスクを実行するマシンが1台でよかったので、flyコマンドでスケールするマシンを1に設定しました。

fly scale count cron=1

参考

https://qiita.com/solt9029/items/bd6a9bae247f74f3e3a2

Discussion