22
11

More than 3 years have passed since last update.

dockerで立ち上げたRailsのキャッシュストアをRedisに設定する

Last updated at Posted at 2020-01-02

docker-composeを用いてRailsサーバをAPIとして立ち上げ,
Reactで書いたフロントからAPIを叩く構成でアプリケーションを開発しています.

API側の負荷を抑えるため, クエリ結果をキャッシュするためにRedisを導入した時のメモになります.
Docker, docker-composeを用いた環境構築やRedisの概要には触れていませんのでご了承ください.

開発環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.1
BuildVersion:   19B88
$ docker -v
Docker version 19.03.1, build 74b1e89
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b

Redis導入前

Dockerfile
FROM ruby:2.6.5-slim

# db, js関係の環境をインストール
RUN apt-get update -qq && apt-get install -y mariadb-client libmariadb-dev-compat build-essential apt-transport-https curl imagemagick && \
    curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
    apt-get install -y nodejs && \
    curl -sS http://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

# Rails (bundle install)
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp


docker-compose.yml
version: "3"
services:
  web:
    build: .
    command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p '3001' -b '0.0.0.0'"
    environment:
      - DATABASE=myapp_development
      - DATABASE_USER=root
      - DATABASE_PASSWORD=password
      - DATABASE_HOST=db
    volumes:
      - .:/myapp
    ports:
      - 3001:3001
    depends_on:
      - db

  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    environment:
      - MYSQL_DATABASE=myapp_development
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - mysql_vol:/var/lib/mysql
    ports:
      - 3306:3306

  volumes:
    mysql_vol:


config/environments/development.rb
Rails.application.configure do
  # 略
  # Enable/disable caching. By default caching is disabled.
  # Run rails dev:cache to toggle caching.
  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = true
    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false
    config.cache_store = :null_store
  end
  # 略
end

Redisの導入

1. キャッシュの有効化

先ほど載せたDockerfileを除く2つのファイルを編集する
...前に, 先にやっておくことがあります!!

config/environments/development.rb のコメントにあるように,
Railsのdevelopment環境ではデフォルトでキャッシュが無効になっているのです.
これに気付かず, かなりハマってました...😅

Enable/disable caching. By default caching is disabled.
Run rails dev:cache to toggle caching.

ということで, 書いてあるコマンドをそのまま実行します.

$ docker-compose run web rails dev:cache
Starting myapp_db_1    ... done
Development mode is now being cached.


2. Redisコンテナの作成

docker-composeで起動させるコンテナにRedisを追加します.

docker-compose.yml
version: "3"
services:
  web:
  # 略
    depends_on:
      - db
+     - redis

  db:
  # 略
+ redis:
+   image: redis
+   ports:
+     - 6379:6379
+   volumes:
+     - "./app/redis:/data"

volumes:
  mysql_vol:


3. キャッシュストアの設定

Gemfileに必要なgemを追加後, ビルドしてbundle installを走らせます.

Gemfile
#+ gem 'redis'
+ gem 'redis-rails'
$ docker-compose build

Railsでのキャッシュ先を, 先ほど追加したRedisコンテナに指定します.
後ほどの動作確認のため, 保存期限は短めに設定しておきます.

config/environments/development.rb
Rails.application.configure do
  # 略
  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = true
-   config.cache_store = :memory_store
+   config.cache_store = :redis_store, 'redis://redis:6379/0', { expires_in: 1.minute }
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false
    config.cache_store = :null_store
  end
  # 略
end

設定は以上で完了です 🎉


4. 動作確認

Redisコンテナ

まずはコンテナを再起動させて, Redisコンテナが正常に動作していることを確認しましょう.
コンテナ内にアタッチしてredis-cliを起動後, 以下のようにRedisのコマンドが実行できればokです.

$ docker-compose up -d
Creating myapp_db_1    ... done
Creating myapp_redis_1 ... done
Creating myapp_web_1   ... done
$ docker exec -it myapp_redis_1 /bin/bash
root@05aaca0b40db:/data# redis-cli
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name 'hoge'
OK
127.0.0.1:6379> get name
"hoge"
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> keys *
(empty list or set)

Redisコマンド一覧はこちら

Rails.cacheを使ってみる

いよいよRailsでキャッシュを使ってみましょう.
ここでは以下のコマンドを使用します.

  • Rails.cache.write(key, value) : キャッシュデータを保存
  • Rails.cache.exist?(key) : key を持つキャッシュデータがあるか確認
config/routes.rb
Rails.application.routes.draw do
  get 'hoge/:id', to: 'redis_samples#hoge'
end
app/controllers/redis_samples_controller.rb
class RedisSamplesController < ApplicationController
  def hoge
    Rails.cache.write('name', 'hogehoge') if params[:id].to_i > 0
    render json: Rails.cache.exist?('name')
  end
end


コンソールからAPIを叩きます.
最初はパラメータに id = 1 を与えてキャッシュデータを保存します.
もちろんtrueが返ってきます.

$ curl localhost:3001/hoge/1
true


実際にRedisコンテナからキャッシュストアを見てみると,
先ほど保存したキャッシュデータが保存されていることが確認できます!
また, ttlコマンドでキャッシュデータの有効期限の残りを秒単位で取得できます.

$ docker exec -it myapp_redis_1 /bin/bash
root@05aaca0b40db:/data# redis-cli
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"\x04\bo: ActiveSupport::Cache::Entry\t:\x0b@valueI\..."
127.0.0.1:6379> ttl name
(integer) 49

指定した有効期限を経過した後に実行すると,
きちんとキャッシュデータが削除されていることも確認できます.

127.0.0.1:6379> keys *
(empty list or set)


最後に削除されたことをRails側からも確認しましょう.
パラメータを id = 0 としてAPIを叩くとfalseが返ってきます.

$ curl localhost:3001/katagamis/hoge/0
false

終わりに

さくっとできるかと思いきや結構手間取ってしまい, 忘れないうちにメモとして残しておきました.
まるっとチュートリアル的な記事ではないので, 開発進めてく途中の参考程度になれば幸いです.
ご意見・質問などあれば遠慮なく!!

参考記事

22
11
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
22
11