1
0

More than 1 year has passed since last update.

Carrierwaveとfog-awsを利用したS3へのアップロードが正常にできるまでに試したこと

Last updated at Posted at 2022-11-22

概要

下記の記事を参考に、Carrierwaveとfog-awsを利用したS3へのアップロードができるように設定した。

本番環境へデプロイ後、動作を確認してみると、下記の状況となっていた。

  • 画像をアップロードしても、
    • S3バケットには何も表示されない
    • /var/www/my-app/current/public/uploads配下に保存されている
  • アクセスはできるが、CSSが反映されなくなっている

環境

  • アプリ

    • ruby 3.0.2
    • rails 6.1.4
    • mysql 8.0.31
  • EC2AMI

    • Amazon Linux2 AMI
    • app server : Unicorn
    • web server : Nginx

エラー①

/var/www/my-app/current/logをそれぞれ確認。
関係ありそうなのは下記のログ。

var/www/my-app/current/log/unicorn.stderr.log
/var/www/my-app/shared/bundle/ruby/3.0.0/gems/carrierwave-2.2.2/lib/carrierwave/storage/fog.rb:68:in `eager_load': uninitialized constant Fog (NameError)

試したこと①

config/initializers/carrierwage.rbの記述の順番を変える。

参考

Moving config.storage = :fog after config.fog_credentials = ... line will solve it.

変更前

carrierwave.rb
if Rails.env.production?
  CarrierWave.configure do |config|
    config.storage = :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory = 'S3バケット名'
    config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/S3バケット名'
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id),
      aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key),
      region: 'ap-northeast-1'
    }
  end
end

変更後

carrierwave.rb
if Rails.env.production?
  CarrierWave.configure do |config|
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id),
      aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key),
      region: 'ap-northeast-1'
    }
    config.storage = :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory = 'S3バケット名'
    config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/S3バケット名'
  end
end

結果

デプロイし直したが変わらず。

試したこと②

エラー原因を探るため、carrierwave.rb等の設定を細かく調整したい。
そこで、EC2上でcarrierwave.rbを修正→unicorn再起動を実施。
そうすると、ひとまずCSSは反映された。
ただし、画像の投稿については、投稿ボタン押下すると、

We're sorry, but something went wrong.

のエラーとなった。

エラー②

ログ

var/www/my-app/current/log/production.log
~(省略)~The bucket does not allow ACLs~(省略)~

画面上でもエラーが出ている状態。

ChromeのConsole
✖︎ GET https://s3-ap-northeast-1.amazonaws.com/バケット名/uploads/user/image/5/画像.jpeg 403 (Forbidden)

試したこと③

上記のエラーから、S3の権限設定が怪しい。

参考

こちらを参考に、バケットの設定を変更。

  • バケットを選択
  • アクセス許可
  • オブジェクト所有者
  • ACL有効に切り替え
  • オブジェクト所有者をオブジェクトライターに設定
    image.png

※ACLを無効にして設定する方法はこちらに追記

結果

  • 画像の投稿、表示ともに正常にできた。
  • S3バケットにアップロードされていることが確認できた。

補足

上記までの設定を行った上で、

  • 当件とは無関係の箇所を修正し、Capistranoでデプロイ
  • ブラウザでアクセスできることを確認(CSSは反映されている)
  • 画像を投稿

すると、再度下記のエラーが発生し、CSSも反映されなくなった。

We're sorry, but something went wrong.

  • 再度unicornを再起動
  • 画像を投稿
    すると、正常に投稿ができた。

ただ、自動デプロイ後の時点で正常な動作ができないと困るため、ログを調査して対応。

var/www/my-app/current/log/production.log
# 該当コントローラのPOST直後
~(省略)~ Completed 500 Internal Server Error in 188ms (ActiveRecord: 0.7ms | Allocations: 2273) ~(省略)~
~(省略)~ ArgumentError ( is not a recognized provider): ~(省略)~

config/initializers/carrierwage.rbがうまく読み込めていない?

参考

最終的には、前述の「変更後」のcarrierwave.rb冒頭に、requireを追加すると、デプロイ直後から正常な状態で動作することが確認できた。

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

if Rails.env.production?
  CarrierWave.configure do |config|
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id),
      aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key),
      region: 'ap-northeast-1'
    }
    config.storage = :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory = 'S3バケット名'
    config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/S3バケット名'
  end
end

※require追加を反映する直前にEC2インスタンスの再起動を行ったので、そちらも影響しているかも?

最後に

  • ACLは昔から存在している制御機能であり、大まかな設定しかできない
  • ポリシーでの管理では、細かい設定ができる
  • 現在はACL無効を選択できるようになり、アクセス制御はポリシーによって一括管理することが可能となった
    とのことなので、ポリシーによる制御を実現していきたい。

参考

追記

var/www/my-app/current/log/production.log
~(省略)~The bucket does not allow ACLs~(省略)~

こちらのエラーの対応方法について、
config/initializers/carrierwage.rbにconfig.fog_public = false を記述することで、下記設定でもS3へのアップロードが可能になることがわかった。

  • ACL無効
  • (IAMポリシーにAmazonS3FullAccessをアタッチしていれば)S3バケットポリシーは記述なしでOK
    ※CloudFrontをOAIで利用する場合は、S3バケットポリシー設定が必要。
  • パブリックアクセスは全てブロックしてOK

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0