【Rails】Sidekiq用コンテナで非同期処理を蹴っ飛ばす
dockerコンテナでホストしたrailsでの非同期処理実行環境を整えるまでの備忘録です。
「一つのコンテナ、一つの責務」がdockerの基本なので、下記をそれぞれ別立てで揃えていきます。
- rails用コンテナ
- sidekiq実行用コンテナ
- redis用コンテナ (sidekiqのキューイングに使う )
一般的に推奨するのは、1つのサービスごとにコンテナを使い、懸念事項の領域を分ける方法です。
コンテナ作成
docker-compose.yml
compose.ymlで必要なコンテナを定義します。
app_containerとsidekiq_containerはbuild時に処理が必要なのでDockerfileに切り出します。
ポイントは一点で、sidekiqを実行するコンテナはgemやconfig/sidekiq.yml
を必要とするのでrailsを実行するコンテナをマウントする必要があります。
volumes: - .:/workspace
で定義app_containerとsidekiq_containerが同じディレクトリをマウントすることで実現されています。
version: '3'
services:
app:
container_name: app_container
build:
context: ./.docker/app/Dockerfile
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DEV_DATABASE: ${POSTGRES_DEV_DATABASE}
POSTGRES_TEST_DATABASE: ${POSTGRES_TEST_DATABASE}
POSTGRES_PRO_DATABASE: ${POSTGRES_PRO_DATABASE}
volumes:
- .:/workspace
tty: true
stdin_open: true
ports:
- 3000:3000
sidekiq:
container_name: sidekiq_container
build:
context: ./.docker/sidekiq/Dockerfile
volumes:
- .:/workspace
depends_on:
- redis
redis:
container_name: redis_container
image: redis:7.0
env_file: .env
command: redis-server --appendonly yes
ports:
- 6379:6379
db:
container_name: db_container
image: postgres
ports:
- 5432:5432
volumes:
- rails_db_volume:/var/lib/postgresql/data
environment:
POSTGRES_ALLOW_EMPTY_PASSWORD: "yes"
POSTGRES_ROOT_PASSWORD: ${POSTGRES_ROOT_PASSWORD}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DEV_DATABASE: ${POSTGRES_DEV_DATABASE}
volumes:
rails_db_volume:
Dockerfile
次に、Dockerfileを定義します。
今回はsidekiqコンテナが記事のスコープなので、app_containerのDockerfileに関する説明は行いません。
Dockerfileでは、rubyイメージのbuildと、bundle install
に必要なプロセスを定義しています。
最終行で、独自の/config/sidekiq.yml
で書いた設定を読み込んでsidekiqを実行するように定義しています。
FROM ruby:3.2.2-alpine3.18
RUN apk update -qq && apk add gcompat libpq-dev nodejs vim g++ make
WORKDIR /workspace
COPY ../ ../
RUN bundle install
CMD [ "bundle", "exec", "sidekiq", "-C", "config/sidekiq.yml" ]
rails側の設定
Gemfile
sidekiq
とredis
のインストールが必要です。
gem "redis", "~> 5.0"
gem 'sidekiq', '~> 7.2'
sidekiq設定
使用するsidekiqの設定を行います。
concurrency
でキューサービスに保持できるjobの数を設定。
queuea
で使用するキューの種類を設定。
:verbose: false
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 10
:queues:
- default
- mailers
redis設定
sidekiqが使用するredisサーバの設定を行います。
url: 'redis://redis:6379/0'
でhostとportを指定することで、コンテナとして定義したredisを使用するように定義しています。
Sidekiq.configure_server do |config|
config.redis = { url: 'redis://redis:6379/0' }
end
Sidekiq.configure_client do |config|
config.redis = { url: 'redis://redis:6379/0' }
end
route定義
sidekiqコンソールを確認するためのパスを定義します。
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
require 'sidekiq/web'
mount Sidekiq::Web, at: "/sidekiq"
# other paths
end
http://localhost:3000/sidekiq/
job作成
job_itemsテーブルにcreate処理を行うjobを作成します。
% rails g job example_job
class ExampleJob < ApplicationJob
queue_as :default
def perform(*args)
JobItem.create!(name: 'name01', user_id: "1")
end
end
実行↓
% rails c
[1] pry(main)> ExampleJob.perform_later
pid=28 tid=2qo INFO: Sidekiq 7.2.0 connecting to Redis with options {:size=>10, :pool_name=>"internal", :url=>"redis://redis:6379/0"}
Enqueued ExampleJob (Job ID: 0f3da019-b58b-4eae-9bd8-29ef7c12a0c0) to Sidekiq(default)
=> #<ExampleJob:0x00007fae51456120
@arguments=[],
@exception_executions={},
@executions=0,
@job_id="0f3da019-b58b-4eae-9bd8-29ef7c12a0c0",
@priority=nil,
@provider_job_id="04cf9d1e5cde6a21aa18d42d",
@queue_name="default",
@successfully_enqueued=true,
@timezone="UTC">
[2] pry(main)> JobItem.all
JobItem Load (1.9ms) SELECT "job_items".* FROM "job_items"
=> [#<JobItem:0x00007fae51713fc0
id: 7,
name: "name01",
user_id: 1,
created_at: Wed, 31 Jan 2024 23:24:50.961593000 UTC +00:00,
updated_at: Wed, 31 Jan 2024 23:24:50.961593000 UTC +00:00>]
jobの実行でcreateが成功しているので、sidekiqコンソールを確認してみます。
sidekiqを通してjobの実行に成功しています。
メトリクスのページに飛ぶと、アプリケーション内で管理されるjobの実行状況を一覧で確認できたりもします。
今回は以上になります。
ここまで読んでいただき、ありがとうございました。
Discussion