Rails8 + Cloudflare R2を試してみた
こんにちは。今回はRails8 + Cloudflare R2を試す機会があったのでそれをまとめていこうと思います。
Cloudflare R2はS3互換のストレージでS3と同様に利用出来ます。また毎月無料枠があるので少量利用目的だととても助かります。
それでは早速始めましょう!
以下が今回Cloudflare R2を試した状態の環境です
環境
- Rails 8.1.2
- Ruby 4.0.1
画像アップロードにはActiveStorageを利用します
必要なもののインストール
画像処理系のライブラリをローカルに入れておくことが必要なのでもしImageMagickかvipsが入っていなければ以下から入れる
依存先ライブラリとかはREADME読むとわかる
brew install imagemagick # or vips
Gemfileに以下を追記して bundle install
gem 'image_processing', '~> 1.0'
gem 'aws-sdk-s3', require: false
ActiveStorageのインストールも終わっていなければ入れます。ActiveStorageのmigrationも作成されるので必要であればここらへんでコミットしとくといいかも。
bin/rails active_storage:install
bin/rails db:migrate
環境別設定など
ストレージ設定
今回は以下のようにcloudflareという環境を作成します
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
cloudflare:
service: S3
access_key_id: <%= ENV["CLOUDFLARE_R2_ACCESS_KEY_ID"] %>
secret_access_key: <%= ENV["CLOUDFLARE_R2_SECRET_ACCESS_KEY"] %>
endpoint: <%= ENV["CLOUDFLARE_R2_ENDPOINT"] %>
bucket: <%= ENV["CLOUDFLARE_R2_BUCKET"] %>
region: <%= ENV.fetch("CLOUDFLARE_R2_REGION", "auto") %>
force_path_style: true
request_checksum_calculation: when_required
response_checksum_validation: when_required
force_path_style: true, request_checksum_calculation: when_required, response_checksum_validation: when_required がないとうまくアップロードが出来ませんでした。
force_path_style はS3互換ストレージを使うときに必要そう。 request_checksum_calculation, response_checksum_validation についてはリクエストやレスポンス送信/受信時にデータ整合性の検証のために設定しておく必要がありそう。
以下の記事を参考にさせていただきました、ありがとうございます!
環境変数
今回の環境では .env を使って環境変数を設定しているのでそこに書く想定ですが設定値は各々の設定箇所で。
Rails8.2からは Rails.app.creds で 1)ENV, 2)credentialsの順で値を取得できるぽいのでそこらへんを使うのも良さげ🎉
以下に設定する値は
- https://dash.cloudflare.com/ にアクセス
- ストレージとデータベース->R2オブジェクトストレージ->概要 にアクセス
- 「バケットを作成」から「バケット名」を入力し「バケットを作成」をクリック
-
- のページの右下のAccount Detailsの「API Tokens」項目にある "Manage"をクリック
- 「Account APIトークンを作成する」をクリック
- 後から見てもわかりやすい「トークン名」を入力し、「管理者読み取りと書き込み」のラジオボタンを有効にしてトークン作成
- 必要な情報が揃ったので環境変数に入れていく
CLOUDFLARE_R2_ACCESS_KEY_ID=your_access_key_id # 6で取得したもの
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_access_key # 6で取得したもの
CLOUDFLARE_R2_ENDPOINT=https://<ACCOUNT_ID>.r2.cloudflarestorage.com # 2のS3 APIっていうURL
CLOUDFLARE_R2_BUCKET=your-bucket-name # 3で設定したバケット名
CLOUDFLARE_R2_REGION=auto
Rails環境別設定
今回は本番環境のみCloudflare R2を使い、その他の環境ではローカルを利用するように設定
# config/environments/development.rb
config.active_storage.service = :local
# config/environments/production.rb
config.active_storage.service = :cloudflare
# config/environments/test.rb
config.active_storage.service = :test
Railsのモデルへ設定
今回はUserモデルに1つのavatarという画像を設定したかったので以下のように記述
class User < ApplicationRecord
has_one_attached :avatar
end
ここで最低限の設定は終わったので簡単にテストしてみましょう。
コンソールから適当なものをアップロードしてみます
bin/rails c
user = User.first
# R2にtest.txtをアップロード
user.avatar.attach(
io: StringIO.new('Hello R2!'),
filename: 'text.txt',
content_type: 'text/plain',
service_name: :cloudflare,
) # => これでtext.txtというファイルがアップロードされるはず
# 確認
user.avatar.attached?
user.avatar.key
# DLしてみて中身を確認
user.avatar.download # => "Hello R2!"
# テスト終わったので削除
user.avatar.purge
これで最低限の設定が終わりました!後は画面からアップロードできるようにしたりアップロードできるもののvalidationを追加したりは適宜行えば良さそうです。
本番環境(Fly.io)へデプロイ
最後に今回はflyioを使っているのでそこにデプロイしておきます。
環境変数などをflyioに設定したあとにデプロイする必要があるので各自必要に応じて変更して環境変数を設定しましょう。
fly secrets set CLOUDFLARE_R2_ACCESS_KEY_ID=xxx
fly secrets set CLOUDFLARE_R2_SECRET_ACCESS_KEY=xxx
fly secrets set CLOUDFLARE_R2_ENDPOINT=https://xxx.r2.cloudflarestorage.com
fly secrets set CLOUDFLARE_R2_BUCKET=your-bucket-name
flyioのconsoleから先程のテストを行えばファイルがアップロードできるかどうかも試せるので試してみると環境変数が設定されているかわかるかと思います🎉
Discussion