Docker環境のRailsでRedisを使う

DockerでRails動かしてさらにRedisを使えるようにします。
DockerでRailsを動かす方法は以下を参照してください。
DockerでRailsを動かす

RailsにRedisを導入

GemfileにRedisを追加します。

  • Gemfile
gem 'redis'

Docker上でbundle installできるように、DockerfileにRUN bundle config set --local frozen falseを追記します。

  • Dockerfile
# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle config set --local frozen false  ←ここに書く
RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile

docker-compose.ymlにRedisの設定を追記します。
全体としては以下のようになります。

  • docker-compose.yml
services:
  db:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: postgres

  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis
    environment:
      - RAILS_ENV=development
      - NODE_ENV=development

  redis:
    image: redis:latest
    ports:
      - "6379:6379"
    volumes:
      - ./data/redis:/data

イメージをビルドします。

docker compose build

次に、config/environments/development.rbの設定です。

config.cache_store = :memory_store

となっている部分を書き換えます

  • config/environments/development.rb
config.cache_store = :redis_cache_store, {url: "redis://redis:6379/0"}

に書き換えます。

さらに、development環境でキャッシュを有効化するため、touchコマンドでtmp/caching-dev.txtを作成します。

touch tmp/caching-dev.txt

これでRedisでキャッシュを利用する準備ができました。

キャッシュが効いているか確認する

実際にキャッシュが効くか試していきます。

適当なモデルとコントローラ、ビューを作成します。

docker compose run web rails g scaffold User name:string age:integer

db:migrateします。

docker compose run web bin/rails db:migrate

app/views/users/index.html.erbにユーザーの平均年齢を表示するよう編集します。

  • index.html.erb
<p style="color: green"><%= notice %></p>

<% content_for :title, "Users" %>

<h1>Users</h1>
<% if @users.exists? %>
  <% 
    average = Rails.cache.fetch(:average, expires_in: 60.seconds) do
      @users.sum(&:age) / @users.size
    end
  %>
<%= "平均年齢は #{average}" %>
<% end %>
<div id="users">
  <% @users.each do |user| %>
    <%= render user %>
    <p>
      <%= link_to "Show this user", user %>
    </p>
  <% end %>
</div>

<%= link_to "New user", new_user_path %>

Railsを立ち上げます。

docker compose up

http://localhost:3000/users/newにアクセスして、適当なユーザを1人作ります。
http://localhost:3000/usersにアクセスして、表示を確認します。

これで平均年齢がキャッシュに保存されました。

次に、年齢の異なる二人目のユーザを登録し、再度http://localhost:3000/usersにアクセスして、表示を確認します。(60秒以内にやる必要があります!)

キャッシュが効いているため、平均年齢が再計算されていません。
最初の表示から60秒以上経過してから画面をリロードすると、キャッシュが捨てられるので平均年齢が再計算されることがわかります。

おわり

Redisを導入してキャッシュを有効化できました。
実際のアプリで使う場合は平均年齢が変わったタイミングで再計算するために、ユーザーの年齢に関する操作が行われたタイミングでキャッシュを捨てる必要があります。