#はじめに
Ruby on Rails 5.2からAWS S3へ画像をアップロードをするため、CarrierWave+fogを使って実装を進めました。
対象
EC2構築、デプロイ経験のある方
EC2へ画像をアップロードしていた方
はじめてS3を利用する方
#AWSの設定
##S3作成
S3 バケットを作成する方法
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/user-guide/create-bucket.html
- 東京リージョン
- バージョニング有効
- Static website hosting有効
- パブリックアクセスをすべてブロック
{
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::[バケット名]",
"arn:aws:s3:::[バケット名]/*"
],
"Condition": {
"StringEquals": {
"aws:SourceIp": "[EC2のパブリックIP]"
}
}
}
]
}
##VPCエンドポイントの設定
EC2とS3の間でファイルの転送を行います。
-
宛先の選択をします。 AWS services と com.amazonaws.ap-northeast-1.s3 にチェックを入れます。
-
通信したいEC2インスタンスが置かれているVPC と そのサブネットに当てられているルートテーブル を選択します。
- カスタムポリシーの設定
{
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::[バケット名]",
"arn:aws:s3:::[バケット名]/*"
]
}
]
}
作成が完了すると、ダッシュボードにエンドポイントが表示されます。
紐付けたサブネットのルートテーブルを確認すると、エンドポイントを介したS3への経路が追加されています。
##AWS CLIを使ってS3へデータを送信テスト
EC2へ接続
$ ssh -i [keyペアファイル] ec2-user@[パブリックIP]
テストファイルを転送
$ touch test.txt
$ aws s3 mv test.txt s3://YOUR_S3_BUCKET/uploads
s3バケットが閲覧できるか確認
$ aws s3 ls s3://YOUR_S3_BUCKET/ --recursive
#Amazon Linux 2の設定
##ImageMagickを導入
$ yum install -y ImageMagick ImageMagick-devel
##アクセスキーとシークレットアクセスキーの設定
aws configure コマンドが、AWS CLI のインストールをセットアップするための最も簡単な方法です。
詳しくは
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html
https://dev.classmethod.jp/cloud/aws/how-to-configure-aws-cli/
$ aws configure
AWS Access Key ID [None]: AKIAXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: 5my9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]:
設定の確認
$ aws configure list
#Railsの設定
##Gemの設定
gem 'carrierwave'
gem 'rmagick'
gem 'fog-aws'
##ImageUploaderの設定
$ rails g uploader Image
class ImageUploader < CarrierWave::Uploader::Base
# 画像サイズを取得するためにRMagick使用
include CarrierWave::RMagick
# developmentとtest以外はS3を使用
if Rails.env.development? || Rails.env.test?
storage :file
else
storage :fog
end
# 画像ごとに保存するディレクトリを変える
def store_dir
"uploads/#{model.class.to_s.underscore}/#{model.id}/#{mounted_as}"
end
# 許可する画像の拡張子
def extension_whitelist
%w(jpg jpeg gif png)
end
# ファイル名を書き換える
def filename
"#{Time.zone.now.strftime('%Y%m%d%H%M%S')}.#{file.extension}" if original_filename
end
end
##CarrierWaveの設定
# CarrierWaveの設定呼び出し
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'
# 画像名に日本語が使えるようにする
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
# 保存先の分岐
CarrierWave.configure do |config|
# 本番環境はS3に保存
if Rails.env.production?
config.storage = :fog
config.fog_provider = 'fog/aws'
config.fog_directory = '[S3のバケット名]'
config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/[S3のバケット名]'
# iam_profile
config.fog_credentials = {
provider: 'AWS',
# credentialsで管理する場合
aws_access_key_id: Rails.application.credentials.aws[:access_key_id],
aws_secret_access_key: Rails.application.credentials.aws[:secret_access_key],
# 環境変数で管理する場合
# aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"],
# aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
region: 'ap-northeast-1' #東京リージョン
}
# キャッシュをS3に保存
# config.cache_storage = :fog
else
# 開発環境はlocalに保存
config.storage :file
config.enable_processing = false if Rails.env.test? #test:処理をスキップ
end
end
##アップローダーの使い方
作成したUploaderをModelに紐付けます。Userモデルのimageカラムに紐付ける例
class User < ApplicationRecord
mount_uploader :image, ImageUploader
end