Heroku + CarrierWave + S3で画像投稿する方法


1. 作業の流れ

まず最初にS3のバケットを作成します。
最初に行う理由は後からローカルで開発しているRailsのアプリケーションにS3で決めた設定を
入力するからです。

S3のバケットの作り方ですが、参考資料をみて行うと問題なく進みます。

流れとしては、

  1. まずIAMでユーザーを作成する。(ここで作成したアクセスキーIDとシークレットアクセスキーをcarrierwaveの設定で使用する。)
  2. S3のバケットを作成する。(画像を保存する箱を作る)
  3. gemのfog-awsを導入して設定ファイルなどを作成する。

の様に進んでいきます。

1. IAMユーザーの作成

まずAWSにアカウント登録するとrootというめちゃくちゃ強い権限を持ったアカウントが作成される。
公式ではセキュリティ上の観点からrootユーザーを日常的に使用するのは推奨していないのでIAMというサービスを使用して、別の権限のユーザーを日常使い様に作成します。

つまり、自分のAWSアカウントだとしてももう一人権限が小さいユーザーを作って管理するイメージです。※作成方法は最後に書いてあるリンクに記載されています。

2. S3のバケットを作成

画像を保存する箱を作成します。
参考資料ではrootユーザーのままでアクセスできると、書いていますがIAMユーザーでやってもできました。
ここの設定は、すごく丁寧に参考資料にまとめられていたので、そのまま使用すれば問題ないかと思います。

参考資料

上記2つの参考リンクです。ここの通りにやればできます。
【Rails】CarrierWaveチュートリアル

3. fog-awsを導入したRailsの設定諸々

fog-awsは外部のストレージサービスを使用する時に簡単にしてくれるgemくらいの認識でOK

まずfog-awsをインストールする

Gemfile

gem 'fog-aws'

bundle installを実行して

次はどの環境で:fog(S3)を使用するのかをRails側に設定する。

app/uploaders/image_uploader


  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick  <= ここのコメントアウトを外す。

  # Choose what kind of storage to use for this uploader:
  このIf文を追加することで、環境毎にどこに保存するかを指定している。
  この場合はproduction環境のみS3を使用する。

  if Rails.env.development?
    storage :file
  elsif Rails.env.test?
    storage :file
  else
    storage :fog
  end

  ....

次に、事前にAWSで作成したIAMユーザーの情報とS3の情報を設定する。
まず設定ファイルであるcarrierwave.rbconfig/initializersいかに作成する。
この場所におけば、初期化に必要なものと判断されて、自動で読み込まれるので作成してしまって構いません。

touch config/initializers/carrierwave.rb

上記コマンドでファイルを作成して設定を記載します。

config/initializers/carrierwave.rb

unless Rails.env.development? || Rails.env.test? <= プロダクション環境のみ動作する。
  require 'carrierwave/storage/abstract'
  require 'carrierwave/storage/file'
  require 'carrierwave/storage/fog'

  CarrierWave.configure do |config|
    config.storage :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory = 'carrierwave-test-app' <=作成したS3のバケット名を記入
    config.fog_credentials = {
        provider: 'AWS',
        aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), #最初にコピーしたIAMユーザーのaccess_key
        aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), #最初にコピーしたIAMユーザーのaws_secret_access_key
        region: 'ap-northeast-1' <=作成したS3のリージョンを記入。
    }
  end
end

コメントを入れているところを細かく説明していくと

unless Rails.env.development? || Rails.env.test? <= プロダクション環境のみ動作する。

ここはそのままです。

config.fog_directory = 'carrierwave-test-app' <=作成したS3のバケット名を記入

最初に作成したS3のページに行って確認してみると良いです。
タイポがないか確認もしましょう。

aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), #最初にコピーしたIAMユーザーのaccess_key
aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), #最初にコピーしたIAMユーザーのaws_secret_access_key

ここではcredentials.yml.encにIAMユーザーのaccess_keyaws_secret_access_keyを指定している。
理由はここに直接記入してしまうとgithubなどでファイルを共有できなくなってしまうので環境変数に入れて外からわからない様にしています。

今回はcredentials.yml.encを使用しましたが参考記事ではdotenv-railsが使用されています。
要は外部からキーの中身を見えなくするという目的がある事を抑えておくと良いです。

■参考資料

【Rails】dotenv-railsの導入方法と使い方を理解して環境変数を管理しよう!

production環境でテストする。

ここまで、設定し終わったらproduction環境でS3に画像がアップされているかテストしてみようと思います。

production環境の設定方法を現場Rails(p274〜)に記入されているのでそちらを参考にしてやってください。

最初にアセットプリコンパイル。

ターミナル

bin/rails assets:precompile

静的ファイル配信サーバを設定

cofig/environments/production.rb

config.public_file_server.enabled = ENV[:RAILS_SERVE_STATIC_FILES]

これをtrueにしたいので

~/.bash_profile

export RAILS_SERVE_STATIC_FILES = 1

とするとtrueになる。

production環境のデータベース作成

rails db:createではデフォルトではdevelopmentとtestしかDBが作成されないので
production用も作成する。

postgresqlの場合

createuser -d -P アプリ名
パスワードを聞かれるので確認用も含めて2回記入して終了

config/database.ymlに反映させる作業

~/.bash_profile

export App名_DATABASE_PASSWORD = 設定したパスワード

ここまでやるとproduction環境でサーバーを立ち上げてみましょう。

ターミナル

bin/rails s --environment=production

これでサーバーが立ち上がるはずです。この辺りは現場Railsを買って読むと、詳しく書いています。
現場Rails

ここで画像を投稿して正しく表示されれば設定が間違っていなければS3にもアップロードされているはずです。

長々と読んでいただきありがとうございます。
間違いなどありましたら、教えていただければありがたいです。

その他

ここではあくまで、carrierwaveとS3の連携に対して話をしましたのでherokuなどの設定には触れていません。
下記に参考になる記事を載せておきますので役立ててください。

■Railsアプリのデプロイ

【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】

■master_keyのコピーの仕方(最後に乗ってる)

Herokuで画像を投稿できるようにする方法(ActiveStorage + Amazon S3)