1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

dockerでRails8+sidekiq+Redis環境構築

Posted at

Rails8でキュー処理の環境をつくる

Rails8のバックグラウンドキュー処理(ActiveJob)をsidekiqで。
Redisもdockerで構築する。

RailsとSidekiqが連携する仕組み

  • Rails側でジョブを登録する
     → 「やってほしい仕事」をキュー(Redis)に入れる
  • Sidekiq側がそのキューを見てる
     → Redisからジョブを取ってきて、処理を実行する
  • RailsとSidekiqは「Redisを介して」間接的につながっている

まずはRails8の環境構築

  • 参考

  • sidekiqディレクトリを作成し、compose.yamlを作成
mkdir sidekiq
cd sidekiq && touch compose.yaml
  • backendディレクトリを作成し、更に配下にapiディレクトリを作成
mkdir backend && mkdir backend/api
  • 必要ファイル(Dockerfile,Gemfile,Gemfile.lock)作成
cd backend && touch {Dockerfile,Gemfile,Gemfile.lock}
この時点でのディレクトリ構成
sidekiq/
├── backend/
│   ├── Dockerfile
│   ├── Gemfile
│   ├── Gemfile.lock
│   └── api/
└── compose.yaml
  • Dockerfile
Dockerfile
FROM ruby:3.3.0
ENV APP /api
ENV TZ Asia/Tokyo
WORKDIR $APP
ADD Gemfile $APP/Gemfile
ADD Gemfile.lock $APP/Gemfile.lock
RUN bundle install
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
  • Gemfile
Gemfile
source 'https://rubygems.org'
gem "rails", "~> 8.0.0"
  • compose.yaml
compose.yaml
services:
    api:
        build: ./backend/
        platform: linux/x86_64
        environment:
          TZ: Asia/Tokyo
        volumes:
          - type: bind
            source: ./backend/api
            target: /api
          - type: volume
            source: gemdata
            target: /usr/local/bundle
        ports:
          - "3000:3000"
volumes:
   gemdata:

最低限のRails環境を構築する(apiモード+minimal)

  • rails new
    まずはノーマルのapiモードでrails new。
    minimalだとactive-jobがskipされるので--no-skip-active-jobオプションをつける。
docker compose run --rm api rails new . --api --minimal --no-skip-active-job

ずらずらずら
backend/apiにインストールされる。

  • api/config/environments/development.rbに以下を追加
api/config/environments/development.rb
config.hosts.clear

この状態でrailsを起動

docker compose up -d

Rails8の起動を確認。

Redisコンテナの追加

「Redis」は、Railsそのものの機能ではなく、オープンソースのインメモリデータストアです。バックグラウンドジョブのキュー管理: 例えば、Sidekiq などのジョブキューライブラリが、ジョブの状態管理やキューとしてRedisを利用します。

まずredis用のディレクトリを作成
mkdir redis

dockerにredisを設定

compose.yaml
redis:
  image: redis:latest
  volumes:
    - type: bind
      source: ./redis
      target: /data
  ports:
    - "6379:6379"

docker compose upでredisコンテナを作成

(Railsを起動したままだったら、docker compose down後にup)

  • redisの起動確認
docker compose exec redis redis-cli

以下のredisプロンプトが出るのでpingを打ってPONGと返ってきたらOK

127.0.0.1:6379> ping
PONG

これでredisは完了

Railsにsidekiqを追加

  • 参考

sidekiqのgemをinstall

bundle addはGemfileに追加してからinstallする

docker compose run --rm api bundle add sidekiq

configを編集/設定ファイル作成

config/application.rb
module Myapp
  class Application < Rails::Application
# ...  
    config.active_job.queue_adapter = :sidekiq
#...

config/initializersにsidekiq.rbを作成

sidekiq.rbは無いので作成

touch backend/api/config/initializers/sidekiq.rb
config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://redis:6379' }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://redis:6379' }
end

configにsidekiqの設定ファイルを作成

初期状態ではdefautのキューが1つだけなので、設定ファイルを作成し追加。

touch backend/api/config/sidekiq.yml
config/sidekiq.yml
# 基本設定
# デフォルトで同時に5つのジョブを並行処理する。
# スレッド数が5本。
:concurrency: 5
# 環境ごとの設定
# staging 環境とproduction 環境では、並行処理数(スレッド数)を10にする。
staging:
  :concurrency: 10
production:
  :concurrency: 10
# ジョブの優先度
# :queues で、優先的に処理するジョブのキュー順序を指定しています。
# 1. critical(最優先)
# 2. default
# 3. low(最後)
:queues:
  - critical
  - default
  - low

ForemanでRailsサーバーとsidekiqを同時に起動

  • foremanをインストール
docker compose exec api bundle add foreman
  • Procfileを作成し編集
touch backend/api/Procfile
Procfile
web: rm -f tmp/pids/server.pid && bundle exec rails s -b 0.0.0.0
worker: bundle exec sidekiq
  • Dockerfileの最終行に以下を追記
    foremanから起動させる
Dockerfile
# foremanで起動
CMD ["foreman", "start"]
  • Dockerfileをいじったのでbuild
docker compose build

APIモードのRailsではセッションを有効化する

Sidekiq Web UIをAPIモードのRailsで使いたい場合、
セッションを有効化する設定が必要。

# config/application.rb
module YourApp
  class Application < Rails::Application
    # 以下を追加
    # セッション周り追加
    config.middleware.use ActionDispatch::Cookies
    # ここのkeyは何でもいい
    config.middleware.use ActionDispatch::Session::CookieStore, key: '_sidekiq_session'
  end
end

sidekiq Web UIのroute設定

railsのルーティングにsidekiqのキュー確認画面を追加する。

config/routes.rb
require 'sidekiq/web'

Rails.application.routes.draw do
  # 以下を追加
  mount Sidekiq::Web => "/sidekiq"
end
  • dockerを起動する
docker compose up -d

Jobの作成

  • 例としてファイルをコピーするだけのジョブを作成する
docker compose exec api rails g job CopyFile
  • ジョブファイルができるので中身を次のようにする
app/job/copy_file_job.rb
require 'fileutils'
class CopyFileJob < ApplicationJob
  queue_as :default
  def perform(source_path, destination_path)
    # ファイルをコピー
    FileUtils.cp(source_path, destination_path)
    puts "ファイルコピー完了: #{source_path} -> #{destination_path}"
  end
end

動作確認

tmpにtest.txtを作成

touch backend/api/tmp/test.txt

rails cコマンドでCopyFileJobを動かす

docker compose exec api rails c
  • perform_now
    キューに積まないでそのまま実行
    sidekiqにも表示されない
rails c
api(dev) > CopyFileJob.perform_now('/api/tmp/test.txt','/api/tmp/test_cp.txt')
ファイルコピー完了: /api/tmp/test.txt -> /api/tmp/test_cp.txt
  • perform_later
    ActiveJob経由でSidekiqキューに積む
    戻り値はJobオブジェクトになるのでprovider_job_idを取得すればjob IDが表示される。
rails c
api(dev) > job = CopyFileJob.perform_later('/api/tmp/test.txt','/api/tmp/test_cp.txt')
api(dev) > job.provider_job_id
=> "e9160212ef0134245ce7a105"

Sidekiqは完了したジョブの履歴を保存しない

Sidekiqはデフォルトでは完了したジョブの履歴を保存しません。
そのため、標準のAPI (Sidekiq::Queue, Sidekiq::RetrySet, Sidekiq::DeadSet) では完了済みのジョブを取得することはできません。

なんだと...。この辺は別に書きます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?