🖼️

【Rails7】Carrierwaveとfog-awsを使って、画像をAWS S3へアップロードする方法

2024/08/07に公開

はじめに

こんにちは。プログラミングスクールでRuby on Railsを主に学習しているmockeyと申します。
前回作成したアプリで、gem carrierwaveを使ってアバターのアップロード機能を実装しました。
画像の保存自体はローカルでも本番環境でもできていましたが、本番環境で新たにアプリを開いた際に登録したはずの画像が表示されず、デフォルト画像になってしまいました。
調べたところ、herokuでデプロイをした場合、一定時間経つとローカルファイルシステムは一時的なものであり、アプリケーションが再デプロイされるとリセットされるとのこと。
renderでもおそらく同じような原因ではないかと考えました。
永続化させて画像が消えないようにしたいため、ストレージサービスであるAmazon S3を導入することにしました。

前提

  • CarrierWaveを用いてのアップロード機能の実装はすでに終了しているものとします。
  • この記事では環境変数の設定は.envに記載する方法を取っています。別の管理方法もあるので適宜ご自身のアプリや開発環境に合った方法を検討していただけますと幸いです。

.envに記載する場合はもしよければこちらの記事も是非ご覧ください。

バージョン

  • Rails 7.1.3.1
  • PostgreSQL 14.11
  • Tailwindcss 3.4.3
  • daisyUI 4.11.1
  • Docker使用
  • ruby 3.2.3
  • デプロイ: render

AWS S3とは?

【AWS、 AWS S3とは?】初心者でもわかる簡単AWS用語解説【AWS初心者向け】ストレージサービス「Amazon S3」とは?実際に使用してみたによると

AWSとは、ECサイトでお馴染みとなっている「Amazon.com」が提供するクラウドコンピューティングサービスです。世界各国で利用されており、クラウドサービスのなかでもトップクラスの高い人気を誇っています。
AWS S3とはAWSのサービスに含まれる機能のひとつで、「Amazon Simple Storage Service」の略称で容量無制限のストレージサービスです。

S3にはたくさんの特徴的な機能があるため、例えば以下のようなメリットを得ることができます。

  • 柔軟なストレージ機能
  • 耐久性と可用性の高さ
  • 低コストによる運用が可能
  • 静的ファイルの配信
  • 豊富なツールや機能

では早速アプリとAWS S3の連携作業に入っていきましょう。

AWSにサインアップする

こちらからAWSアカウントを作成します。

AWSの設定

  • マネジメントコンソールにアクセスする→サービスをクリック

  • 検索欄でIAMを検索、IAMユーザーを作成する

以下の記事が大変分かりやすいです。
https://syutech-engineer.com/cloud/iam-accesskey-create-step/

Image from Gyazo

  • サイドバーからユーザーを選択

  • ユーザーを追加をクリック

作成したユーザーにS3へアクセスできるように権限を追加します。
Image from Gyazo

  • ユーザーの作成をクリック

Image from Gyazo

下へスクロールすると以下のような項目がある
Image from Gyazo

  • アクセスキーを作成をクリック

Image from Gyazo

  • ローカルコードを選択して次へをクリック

Image from Gyazo
アクセスキーが作成されました。
※もし消してしまったら、再度作り直せばいいようです。
上記ページはキーを控えたのち閉じて大丈夫です。
(アクセスキーは後で使うので保存するかコピペできるようにしておくと🙆‍♀️)

サービス「S3」にてバケットを作成する

バケットとは?

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/UsingBucket.html
Amazon S3 にデータ (写真、動画、ドキュメントなど) をアップロードするには、いずれかの AWS リージョン に S3 バケットを作成する必要があります。

バケットとは、Amazon S3 に保存されるオブジェクトのコンテナです。バケットにはオブジェクトをいくつでも保存でき、アカウントにはバケットを 100 個まで保存できます。

  • 検索欄で「S3」と検索する

    Image from Gyazo

    • バケットを作成をクリックする

      Image from Gyazo

    • 任意のバケット名を入力します。
      公式ドキュメント 命名規則

    • そのまま設定を変更せずに下までスクロールしてバケットを作成します。

      Image from Gyazo

    これでAWSの設定は完了です。

    gem 'fog-aws'のインストール

    fog-awsは、CarrierWaveと連携してAmazon S3に画像やファイルをアップロードするために必要なライブラリ。このライブラリを使用することで、CarrierWaveはAmazon S3と連携し、クラウドストレージにファイルを保存することができます。
    以下公式のREADMEに詳しい設定方法が掲載されています。

https://github.com/fog/fog-aws

Gemfile
gem 'fog-aws'
terminal
% bundle install

→ その後Dockerを再起動させて変更を適用させる

% docker compose restart

.envにアクセスキーとシークレットアクセスキー、リージョン、バケット名の環境変数を設定

.env
#AWS
S3_ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY_ID
S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCSS_KEY
S3_REGION=ap-northeast-1  #東京を意味するようです!
S3_BUCKET_NAME=mokiobucket

* aws_access_key_id S3用に用意したIAMユーザーのアクセスキー
* aws_secret_access_key S3用に用意したIAMユーザーのシークレットアクセスキー
* region S3のリージョン
* config.fog_directory S3のバケット名

config/initializers/carrierwave.rbの設定

config/initializers/carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  if Rails.env.production?
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory  = ENV['S3_BUCKET_NAME']
    config.fog_public = false
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: ENV['S3_ACCESS_KEY_ID'],
      aws_secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
      region: ENV['S3_REGION'],
      path_style: true
    }
  else
    config.storage :file
    config.enable_processing = false if Rails.env.test?
  end
end

アップローダークラスの編集

app/uploaders/avatar_uploader.rb
if Rails.env.production?
  storage :fog
else
  storage :file
end

Rails.env.production? の場合(つまり本番環境)で storage :fog を使用し、それ以外の環境(開発・テスト)では storage :file するように条件分岐させます。

renderにてEnvironment Variables を設定

  • render内、DashboardEnvironmentを開く
  • + Add Environment Variableをクリックして、以下の環境変数を追加
S3_ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY_ID
S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCSS_KEY
S3_REGION=ap-northeast-1  
S3_BUCKET_NAME=mokiobucket

これでrender側の設定も完了です!
この後デプロイを実施し、本番環境で画像が保持されるようになっていれば成功です。

おわりに

今回Carrierwaveでアップロードした画像をAWS S3を使用して画像が永続的に保存できるようにいたしました。
RailsにはRails 5.2以降に標準で統合されたActive Storageという機能で画像アップロードができるライブラリがあるので、今後のアプリ開発の際はActive Storageの使用も検討に入れたいと思います。

ご覧いただきありがとうございました。

参考記事

Discussion