Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
23
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

【AWS S3 + EC2 + CarrierWave + Fog】RailsからS3へ画像アップロード手順

はじめに

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の間でファイルの転送を行います。

  1. VPCのダッシュボードを開き、 エンドポイント の作成ボタンをクリックします。
    aws_vpc_endpoint_01.png

  2. 宛先の選択をします。 AWS services と com.amazonaws.ap-northeast-1.s3 にチェックを入れます。
    aws_vpc_endpoint_02.png

  3. 通信したいEC2インスタンスが置かれているVPC と そのサブネットに当てられているルートテーブル を選択します。
    スクリーンショット 2019-12-22 16.17.56.png

  4. カスタムポリシーの設定

カスタムポリシーの例
{
    "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の設定

Gemfile
gem 'carrierwave'
gem 'rmagick'
gem 'fog-aws'

ImageUploaderの設定

$ rails g uploader Image
/uploaders/image_uploader.rb
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の設定

/config/initializers/carrierwave.rb
# 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カラムに紐付ける例

User.rb
class User < ApplicationRecord
  mount_uploader :image, ImageUploader
end
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
23
Help us understand the problem. What are the problem?