🦈

【LINE通知機能】Docker+Redis+Sidekiq+Active Jobを使いチャットを送信。Renderへのデプロイをする

2024/09/14に公開

はじめに

こんにちは! プログラミング初学者のyukimuraです!
今回は私自身の個人開発したアプリで実装した、LINE通知機能についてのRenderへのデプロイ方法を記述します。
間違いなどありましたら、優しくご指摘いただけましたら幸いです
LINE通知機能の実装自体は前回で既に終わっているので、前回の記事をご覧になってない方は先にそちらをご覧ください
https://zenn.dev/yukimura_n/articles/4f492c85bc7b28

始める前に

今回の実装とは別にRenderへのデプロイ方法に、render.ymlファイルを作成して行う方法があります
こちらは公式にも記載されております
よければこちらの方法も参考にどうぞ
https://zenn.dev/katsumanarisawa/articles/c9da48652f399d#sidekiqのデプロイ
https://docs.render.com/deploy-rails-sidekiq

実装手順

  1. RenderでRedisを作成する
  2. 環境変数を設定する
  3. Dockerfile.sidekiqを作成する
  4. RenderでBackground Worker(sidekiq)を作成する
  5. 実行を確認できたら、時間を調整する

RenderでRedisを作成する

1. 実装を開始します

Render.comのDashboardからRedisを作成してください
Image from Gyazo

  • 作成されたRedisのInternal Redis URLを使用します

環境変数を設定する

1. gem 'dotenv-rails'のインストール

https://github.com/bkeepers/dotenv
Gemfile

gem 'dotenv-rails'

2. bundle install

bundle install

3. .envファイルをルートディレクトリに作成し、環境変数を設定する

## ローカルのURL
REDIS_URL_DEVELOPMENT = "redis://redis:6379"
## 作成されたRedisのInternal Redis URLを使用
REDIS_URL_PRODUCTION = "redis://your-production-redis-url:6379"

4. config/initializers/sidekiq.rbを修正する

Sidekiq.configure_server do |config|
  config.redis = { url: Rails.env.production? ? ENV.fetch('REDIS_URL_PRODUCTION', nil) : ENV['REDIS_URL_DEVELOPMENT'] }
end

Sidekiq.configure_client do |config|
  config.redis = { url: Rails.env.production? ? ENV.fetch('REDIS_URL_PRODUCTION', nil) : ENV['REDIS_URL_DEVELOPMENT'] }
end

5. .gitignoreファイルに下記を記述しないと、git hubに挙げられてしまうので注意

.gitignore

/.env

6. 設定の確認

  • rails コンソールで下記コマンドを実行して、設定した値が返ってきたら成功です
> ENV['REDIS_URL_PRODUCTION']

参考記事
https://qiita.com/yuichir43705457/items/7cfcae6546876086b849

https://qiita.com/Wata16/items/d2d3aa21623f8c026d5d

7. Web Serviceに接続する

  • 作ったRedisのinternal-Redis-urlをWeb ServiceのEnvironmentから追加してください
    Image from Gyazo

Dockerfile.sidekiqを作成する

1. Web Serviceとは別にBackground Worker(sidekiq)を動かすために、Dockerfile.sidekiqを作成します

Dockerfile.sidekiq

ARG RUBY_VERSION=3.2.3
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base

WORKDIR /rails

ENV RAILS_ENV="production" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle" \
    BUNDLE_WITHOUT="development"

FROM base as build

RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential curl git libpq-dev libvips node-gyp pkg-config python-is-python3

ARG NODE_VERSION=20.13.1
ARG YARN_VERSION=1.22.22
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
    npm install -g yarn@$YARN_VERSION && \
    rm -rf /tmp/node-build-master

COPY Gemfile Gemfile.lock ./
RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile

COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

COPY . .

RUN bundle exec bootsnap precompile app/ lib/

FROM base

RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y curl libvips postgresql-client && \
    rm -rf /var/lib/apt/lists /var/cache/apt/archives

COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails

RUN useradd rails --create-home --shell /bin/bash && \
    chown -R rails:rails db log storage tmp
USER rails:rails

CMD ["bundle", "exec", "sidekiq"]
Dockerfileとの違い

Dockerfile

# syntax = docker/dockerfile:1

ARG RUBY_VERSION=3.2.3
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base

WORKDIR /rails

ENV RAILS_ENV="production" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle" \
    BUNDLE_WITHOUT="development"

FROM base as build

RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential curl git libpq-dev libvips node-gyp pkg-config python-is-python3


ARG NODE_VERSION=20.13.1
ARG YARN_VERSION=1.22.22
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
    npm install -g yarn@$YARN_VERSION && \
    rm -rf /tmp/node-build-master

COPY Gemfile Gemfile.lock ./
RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile

COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

COPY . .

RUN bundle exec bootsnap precompile app/ lib/
ENV SECRET_KEY_BASE=Rails.application.config.secret_key_base=ENV['SECRET_KEY_BASE']
RUN ./bin/rails assets:precompile

FROM base

RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y curl libvips postgresql-client imagemagick && \
    rm -rf /var/lib/apt/lists /var/cache/apt/archives

COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails

RUN useradd rails --create-home --shell /bin/bash && \
    chown -R rails:rails db log storage tmp
USER rails:rails

ENTRYPOINT ["/rails/bin/docker-entrypoint"]
EXPOSE 3000
CMD ["./bin/rails", "server", "-b", "0.0.0.0", "-p", "3000"]
  • dockerfileではコンテナができたらこのコマンドが最後に実行されることによってサーバーが立ち上がる
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
EXPOSE 3000
CMD ["./bin/rails", "server", "-b", "0.0.0.0", "-p", "3000"]
  • sidekiqfileだと下記のコマンド。Dockerfileとの差異はここだけ
CMD ["bundle", "exec", "sidekiq"]

2. procfileにコードを記述

web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0.0.0.0 -p 3000
js: yarn build --watch
css: yarn build:css --watch
worker: bundle exec sidekiq #追加

- Procfile(プロックファイル)

HerokuなどのPaaS(Platform as a Service)環境でアプリケーションを動かす際に、どのプロセスをどのように実行するかを定義するファイルです。主に、アプリケーションのWebサーバーの起動方法やバックグラウンドジョブの実行方法を指定します。

- Procfileの役割

Procfileは、アプリケーションで実行するプロセス(仕事の流れ)をHerokuや他のサービスに伝えるために使われます。これがあることで、HerokuがどのコマンドでWebサーバーや他のタスクを実行するのかを理解できるようになります。
https://devcenter.heroku.com/ja/articles/procfile

3. 再buildとupを行う

docker compose build
docker compose up

4. ローカルでは新しいターミナルでsidekiqサーバーを動かす必要がなくなる

  • 前回の記事では、sidekiqを動かすために、新しいターミナルからコンテナに入って
    budle exec sidekiqを実行して行っていたが、Dockerfile.sidekiqの作成と
    procfileにコードを記述したことで、docker compose upだけでsidekiqも立ち上がると思います(redisも同様に)
  • upした時に、4つのコンテナの起動が確認
    Image from Gyazo
  • procfileで設定したコマンドが実行されていることも確認できます
    Image from Gyazo

RenderでBackground Worker(sidekiq)を作成する

1. Render.comのDashboardからBackground Worker(sidekiq)を作成してください

  • この部分で課金が必要になります

2. 作成ができたら、読み込むDockerfile Pathを変更する

  • Background Workerのsettingで読み込むdocker fileをDockerfile.sidekiqにする
    Image from Gyazo

3. Environmentを設定する

  • RedisのURL
  • Railsのマスターキー
  • PostgreSQLのURL...etc
    それぞれを追加して接続する
    Image from Gyazo

4. 確認

  • デプロイの時に、ローカル同様に設定したjobが確認できたら成功です
  • 前回の記事での設定のままなら、2分ごとにチャットが送られているか確認してください
    Image from Gyazo

時間の確認

Regionに東京がないことから、シンガポールに設定していると思われます
シンガポールからは時差が9時間あるために、もし朝7時に送信されて欲しいのであればscheduleでは
22時に送信される設定にしてください

:scheduler:
  :schedule:
    send_line_message_job:
      cron: "0 22 * * *"  # 毎朝7時に実行するためにシンガポールの9時間前に設定
      class: "SendLineMessageJob"
      queue: default

最後に

実装は以上になります
Dockerなどのインフラ知識がまだまだ足りてないことが実感させられた実装でした
きっと他にもっと良い方法があると思いますので、一つの方法として受け止めてもらえたら幸いです

Dokcerについて

https://qiita.com/etaroid/items/b1024c7d200a75b992fc#-イメージimage

- Dockerfile.sidekiqについて

図から、composeは一個一個イメージを作成してbuildするのが面倒だからそのコンテナ作成を,一つのコマンドでまとめてやってくれるもの。。

でもrenderではwebサービスとbaskgroundサーバーをわけてしまっているから、一個一個イメージが必要だったという理解を自分はしています。
https://qiita.com/etaroid/items/88ec3a0e2d80d7cdf87a#docker-composeを利用しない場合
いずれにせよ、まだまだ勉強が必要だと思いました
最後までご覧いただきありがとうございました

参考記事一覧

https://qiita.com/rk2530/items/9bea7317065151c5c588
https://otaku-programmer.com/rails/sidekiq/1/
https://qiita.com/keinko/items/60c844bcf329bd3f4af8
https://qiita.com/tomu28/items/8f13145bd8d45523a195
https://zenn.dev/yoiyoicho/articles/03863702867eb0
https://qiita.com/nysalor/items/94ecd53c2141d1c27d1f
https://qiita.com/Dai_Kentaro/items/efef71b4d2cd0b76f227
https://dev.icare.jpn.com/dev_cat/sidekiq/
https://qiita.com/uggds/items/5e4f8fee180d77c06ee1
https://qiita.com/WisteriaWave/items/1f799fa20f491b37989e
https://qiita.com/lemonade_37/items/296bc211cf3e781c5600

Discussion