Rails6とSidekiqのアプリをDockerで作ってHerokuでリリース

Ruby3.0、Rails6でSidekiqを使ったアプリをDocker上に作る際に引っかかったので、備忘録を書いておきます。

Herokuにリリースします。

参考にしたURL:https://blog.u6k.me/2018/04/29/sample-sidekiq.html

$ mkdir myapp
$ cd myapp

GemfileとGemfile.lock、Dockerfile、docker-compose.ymlを作成して、Gemfileを編集してgem ‘sidekiq’とgem ‘sidekiq-cron’を追加

$ touch Gemfile Gemfile.lock Dockerfile docker-compose.yml
$ cat Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '3.0.1'
gem 'rails', '~> 6'

railsコマンドをDockerコンテナ化する。Dockerfileを作って以下のように編集

FROM ruby:3.0.1

RUN apt-get update && \
    apt-get install -y \
        nodejs postgresql-client && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn && \
    apt-get clean

VOLUME /myapp
WORKDIR /myapp

COPY Gemfile .
COPY Gemfile.lock .

RUN bundle install

EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.ymlを作って以下のように編集

version: '3'

services:
  web:
    build: .
    environment:
      - "RAILS_ENV=development"
      - "REDIS_URL=redis://redis:6379"
    volumes:
      - ".:/myapp"
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis
  worker:
    build: .
    environment:
      - "RAILS_ENV=development"
      - "REDIS_URL=redis://redis:6379"
    volumes:
      - ".:/myapp"
    depends_on:
      - "redis"
    command: sidekiq
  redis:
    image: redis:4.0
    volumes:
      - "redis:/data"
    command: redis-server --appendonly yes
  db:
    image: postgres
    ports:
      - '5432:5432'
    volumes:
      - postgresql-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password

volumes:
  redis:
    driver: local
  postgresql-data:
    driver: local

Docker上でrails new

$ docker-compose run web rails new . --force --no-deps --database=postgresql --skip-bundle

Gemfileを編集してsidekiqを追加

# sidekiq
gem 'sidekiq'
gem 'sidekiq-cron'

イメージをビルドしてwebpackerをインストール

$ docker-compose build
$ docker-compose run web yarn install --check-files
$ docker-compose run web bundle exec rails webpacker:install

トップページをwelcomeページから変えて、config/routes.rbでrequireやmountをしておきます。

$ docker-compose exec web rails g controller home top
require 'sidekiq/web'
require 'sidekiq/cron/web'

Rails.application.routes.draw do
  mount Sidekiq::Web, at: '/sidekiq'
  get "/" => "home#top"
end

config/database.ymlを編集

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>

コンテナを起動

$ docker-compose up -d

dbを作ってマイグレート

$ docker-compose run web rake db:create
$ docker-compose run web rails db:migrate

これでlocalhost:3000を開けば表示されます。

Hello ワーカーを作成します

$ docker-compose exec web rails g sidekiq:worker Hello

app/worker/hello_worker.rbにputs “hello”を追加

class HelloWorker
  include Sidekiq::Worker

  def perform(*args)
    puts "hello"
  end
end

コンテナを再起動してrailsコンソールを開きます

$ docker-compose down -v
$ docker-compose up -d
$ docker-compose exec web rails c

ワーカーをキューに登録します。

> HelloWorker.perform_async

正常に登録された場合、文字列が表示されます。

キューに登録したワーカーはすぐに実行されたことをworkerコンテナのログを確認します

$ docker-compose logs worker
worker_1  | hello

という行があれば実行されています。

sidekiqのcron化をしていきます。

コンテナを再起動してRailsコンソールを開き、

$ docker-compose down -v
$ docker-compose up -d --build
$ docker-compose exec web rails c

sidekiqでクーロンを登録します

Sidekiq::Cron::Job.create name: "Hello Job", cron: "* * * * *", class: "HelloWorker"

ログを確認すると、約1分ごとにジョブが実行されていることがわかります。

docker-compose logs worker
orker_1  | 2021-06-14T21:07:33.930Z pid=1 tid=641 INFO: Booted Rails 6.1.3.2 application in development environment
worker_1  | 2021-06-14T21:07:33.931Z pid=1 tid=641 INFO: Running in ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-linux]
worker_1  | 2021-06-14T21:07:33.932Z pid=1 tid=641 INFO: See LICENSE and the LGPL-3.0 for licensing details.
worker_1  | 2021-06-14T21:07:33.932Z pid=1 tid=641 INFO: Upgrade to Sidekiq Pro for more features and support: https://sidekiq.org
worker_1  | 2021-06-14T21:07:33.933Z pid=1 tid=641 INFO: Booting Sidekiq 6.2.1 with redis options {:url=>"redis://redis:6379"}
worker_1  | 2021-06-14T21:10:10.749Z pid=1 tid=eox class=HelloWorker jid=4b94056a98e35c24d72cf61c INFO: start
worker_1  | hello
worker_1  | 2021-06-14T21:10:11.100Z pid=1 tid=eox class=HelloWorker jid=4b94056a98e35c24d72cf61c elapsed=0.348 INFO: done
worker_1  | 2021-06-14T21:11:03.202Z pid=1 tid=euh class=HelloWorker jid=1e975d07184b6d8b5cd52b45 INFO: start
worker_1  | hello
worker_1  | 2021-06-14T21:11:03.206Z pid=1 tid=euh class=HelloWorker jid=1e975d07184b6d8b5cd52b45 elapsed=0.003 INFO: done
worker_1  | 2021-06-14T21:12:08.061Z pid=1 tid=ev1 class=HelloWorker jid=188bc7a35b13bef271afb3c0 INFO: start
worker_1  | hello
worker_1  | 2021-06-14T21:12:08.065Z pid=1 tid=ev1 class=HelloWorker jid=188bc7a35b13bef271afb3c0 elapsed=0.004 INFO: done
worker_1  | 2021-06-14T21:13:22.170Z pid=1 tid=evl class=HelloWorker jid=6d5f82a01ae29804c9663749 INFO: start
worker_1  | hello
worker_1  | 2021-06-14T21:13:22.173Z pid=1 tid=evl class=HelloWorker jid=6d5f82a01ae29804c9663749 elapsed=0.003 INFO: done

Herokuでリリース

# ログイン
$ heroku login

# herokuのコンテナレジストリにログイン
$ heroku container:login

# アプリ作成
$ heroku create アプリ名

$ heroku config:set HOST=0.0.0.0

$ rm tmp/pids/server.pid      

# イメージを作成してコンテナレジストリにpush
$ heroku container:push web

# postgresqlアドオンの無料プランを追加
$ heroku addons:create heroku-postgresql:hobby-dev

# イメージをherokuへデプロイ
$ heroku container:release web

# DBセットアップ
$ heroku run rails db:migrate

# アクセス
$ heroku open