CarrierWave + MinIO(S3)の構成で画像のアップロードを行う機能を作成します。
ローカルではMinIOにアップロード。本番ではS3にアップロードする設定を行います。
MinIOの設定についてはこちらをご確認ください。
また、ここで作成したソースはGitHubにアップロードしています。(リポジトリ)
実行環境
インストール Gemfileに以下の行を追加します。
gem 'carrierwave', '~> 2.0' gem 'fog-aws'
画像をアップロードするために必要な機能の作成、CarrierWaveの設定を行います。
はじめに、下記のコマンドでアップローダーを作成します。
docker-compose exec app bundle exec rails generate uploader Avatar
作成されたものがこちらです。
class AvatarUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick # include CarrierWave::MiniMagick # Choose what kind of storage to use for this uploader: storage :file # storage :fog # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end # Provide a default URL as a default if there hasn't been a file uploaded: # def default_url(*args) # # For Rails 3.1+ asset pipeline compatibility: # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) # # "/images/fallback/" + [version_name, "default.png"].compact.join('_') # end # Process files as they are uploaded: # process scale: [200, 300] # # def scale(width, height) # # do something # end # Create different versions of your uploaded files: # version :thumb do # process resize_to_fit: [50, 50] # end # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: # def extension_whitelist # %w(jpg jpeg gif png) # end # Override the filename of the uploaded files: # Avoid using model.id or version_name here, see uploader/store.rb for details. # def filename # "something.jpg" if original_filename # end end
今回はMinIOにアップロードするのでストレージの指定をfogにします。
また、MinIOの画像を保存するディレクトリとキャッシュディレクトリの指定をします。
# Choose what kind of storage to use for this uploader: # storage :file storage :fog # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end def cache_dir 'tmp/image-cache' end
作成したら、対象のモデルにマウントします。
class User < ApplicationRecord mount_uploader :avatar, AvatarUploader end
create_table :users do |t| t.string :name t.string :address t.string :email t.string :avatar # 画像の情報を保持する t.datetime :created_at, null: false t.datetime :updated_at, null: false end
config/initializers/carrierwave.rbに設定を記載します。
require 'carrierwave/storage/abstract' require 'carrierwave/storage/file' require 'carrierwave/storage/fog' CarrierWave.configure do |config| config.fog_provider = 'fog/aws' # storage, cache_storageはfog(外部サービス指定) config.storage :fog config.cache_storage = :fog # ブラウザから参照する際のパスを指定(http://ドメイン/バケット名) config.asset_host = 'http://localhost:9000/mybucket' # バケット名 config.fog_directory = 'mybucket' # 認証情報 config.fog_credentials = { provider: 'AWS', aws_access_key_id: 'minio_access_key', aws_secret_access_key: 'minio_secret_key', path_style: true, region: 'ap-northeast-1', host: 'minio', endpoint: 'http://minio:9000' } end # ファイル名に日本語を許可 CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
ポイントは以下の点です。
以上で設定は終了です。
設定が終わったので、実際にMinIOにアップロードできるか確認します。 画像を選択し、
データを更新
MinIOにアップロードできました。
ローカル環境でMinIOに画像をアップロードすることができました。
次は、実際にAWSにデプロイして、EC2からS3にアップロードするための設定を行いたいと思います。
Rails側、AWS側で設定が必要なのでそれぞれ見ていきます。
先ほど修正した、carrierwave.rbを以下のように修正します。
require 'carrierwave/storage/abstract' require 'carrierwave/storage/file' require 'carrierwave/storage/fog' CarrierWave.configure do |config| config.fog_provider = 'fog/aws' # storage, cache_storageはfog(外部サービス指定) config.storage :fog config.cache_storage = :fog case Rails.env when 'production' config.fog_public = false config.fog_directory = 'mybucket-tlog-test' config.fog_credentials = { provider: 'AWS', use_iam_profile: true, path_style: true, region: 'ap-northeast-1' } when 'development' # ブラウザから参照する際のパスを指定(http://ドメイン/バケット名) config.asset_host = 'http://localhost:9000/mybucket' # バケット名 config.fog_directory = 'mybucket' # 認証情報 config.fog_credentials = { provider: 'AWS', aws_access_key_id: 'minio_access_key', aws_secret_access_key: 'minio_secret_key', path_style: true, region: 'ap-northeast-1', host: 'minio', endpoint: 'http://minio:9000' } end end # ファイル名に日本語を許可 CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
productionの場合の設定を新規に追加しました。
今回は、EC2インスタンスにIAMロールを割り当てているので、use_iam_profile: trueと設定し、aws_access_key_id、aws_secret_access_keyは入力していません。
AWS側で画像をS3にアップロードするために必要な設定は以下のものです。
※作成するバケットは特殊な設定は不要で、デフォルトの設定で作成します。
上記の設定が終了し、AWSへのデプロイが終了したら動作確認をしてみます。 画像を選択し、
データを更新
S3にちゃんとアップロードできました。
CarrierWaveを使用して、ローカル環境ではMinIO、本番環境ではS3に画像をアップロードする方法の紹介でした。
CarrierWaveの使い方としては、画像のリサイズ、拡張子の制限など他にも色々な機能が備わっているので時間があれば紹介するかもしれません。
今回は特に設定はしていなかったのですが、キャッシュファイルもS3にアップロードしているので、ライフサイクルを設定し削除することも検討した方が良いです。(今さらだけどS3のライフサイクルを試してみた。) 次は、RailsのActive Storageを使用するケースもやってみたいと思います。