概要
下記の記事を参考に、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/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.
変更前
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
変更後
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.
のエラーとなった。
エラー②
ログ
~(省略)~The bucket does not allow ACLs~(省略)~
画面上でもエラーが出ている状態。
✖︎ GET https://s3-ap-northeast-1.amazonaws.com/バケット名/uploads/user/image/5/画像.jpeg 403 (Forbidden)
試したこと③
上記のエラーから、S3の権限設定が怪しい。
参考
こちらを参考に、バケットの設定を変更。
※ACLを無効にして設定する方法はこちらに追記
結果
- 画像の投稿、表示ともに正常にできた。
- S3バケットにアップロードされていることが確認できた。
補足
上記までの設定を行った上で、
- 当件とは無関係の箇所を修正し、Capistranoでデプロイ
- ブラウザでアクセスできることを確認(CSSは反映されている)
- 画像を投稿
すると、再度下記のエラーが発生し、CSSも反映されなくなった。
We're sorry, but something went wrong.
- 再度unicornを再起動
- 画像を投稿
すると、正常に投稿ができた。
ただ、自動デプロイ後の時点で正常な動作ができないと困るため、ログを調査して対応。
# 該当コントローラの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を追加すると、デプロイ直後から正常な状態で動作することが確認できた。
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無効を選択できるようになり、アクセス制御はポリシーによって一括管理することが可能となった
とのことなので、ポリシーによる制御を実現していきたい。
参考
追記
~(省略)~The bucket does not allow ACLs~(省略)~
こちらのエラーの対応方法について、
config/initializers/carrierwage.rbにconfig.fog_public = false を記述することで、下記設定でもS3へのアップロードが可能になることがわかった。
- ACL無効
- (IAMポリシーにAmazonS3FullAccessをアタッチしていれば)S3バケットポリシーは記述なしでOK
※CloudFrontをOAIで利用する場合は、S3バケットポリシー設定が必要。 - パブリックアクセスは全てブロックしてOK
参考