Log目次

【Rails】CarrierWave + MinIO(S3)環境での画像アップロード処理

作成日 2019-08-22更新日 2019-08-22

はじめに

CarrierWave + MinIO(S3)の構成で画像のアップロードを行う機能を作成します。

ローカルではMinIOにアップロード。本番ではS3にアップロードする設定を行います。

MinIOの設定についてはこちらをご確認ください。

また、ここで作成したソースはGitHubにアップロードしています。(リポジトリ)

実行環境


インストール Gemfileに以下の行を追加します。

gem 'carrierwave', '~> 2.0' gem 'fog-aws'

MinIOに画像をアップロードするための設定

画像をアップロードするために必要な機能の作成、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

CarrierWaveの設定

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:]\.\-\+]/

ポイントは以下の点です。

  • aws_access_key_id、aws_secret_access_keyにはMinIOのアクセス情報を設定します。
  • config.asset_hostにはホストOSのブラウザからMinIOへアクセスするための情報を記載します。
  • config.fog_credentialsのhost、endpointには、RailsのコンテナからMinIOへアクセするための情報を記載します。

以上で設定は終了です。

動作確認

設定が終わったので、実際にMinIOにアップロードできるか確認します。 画像を選択し、

データを更新

MinIOにアップロードできました。

AWSにデプロイして確認してみる

ローカル環境でMinIOに画像をアップロードすることができました。

次は、実際にAWSにデプロイして、EC2からS3にアップロードするための設定を行いたいと思います。

Rails側、AWS側で設定が必要なのでそれぞれ見ていきます。

Rails側で設定する内容

先ほど修正した、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側で設定する内容

AWS側で画像をS3にアップロードするために必要な設定は以下のものです。

※作成するバケットは特殊な設定は不要で、デフォルトの設定で作成します。


動作確認

上記の設定が終了し、AWSへのデプロイが終了したら動作確認をしてみます。 画像を選択し、

データを更新

S3にちゃんとアップロードできました。

まとめ

CarrierWaveを使用して、ローカル環境ではMinIO、本番環境ではS3に画像をアップロードする方法の紹介でした。

CarrierWaveの使い方としては、画像のリサイズ、拡張子の制限など他にも色々な機能が備わっているので時間があれば紹介するかもしれません。

今回は特に設定はしていなかったのですが、キャッシュファイルもS3にアップロードしているので、ライフサイクルを設定し削除することも検討した方が良いです。(今さらだけどS3のライフサイクルを試してみた。) 次は、RailsのActive Storageを使用するケースもやってみたいと思います。

参考