Railsで作ったアプリをAWSでデプロイ⑨　〜S3を利用する〜


前回までにCapistranoの自動デプロイを行いました

今回はAWSが提供するS３という画像ストレージサービスがあるので、
投稿した画像はS3に保存されるよう設定していきたいと思います

まずS3のバゲットを作っていきます
S3用IAMユーザーでログインし、「S3」をサービスから検索します
<img width="1440" alt="スクリーンショット 2020-03-12 15.37.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/1aada44d-0258-0169-8ffb-87254af9b80e.png">

すると下記画面になりますのでバゲット名、リージョンを選択（最寄りのサーバーを選択）
<img width="1440" alt="スクリーンショット 2020-03-12 15.39.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/02dc2e74-07c7-bee7-0de8-6c3c53a7d411.png">

次の画面は何もせず次へ
<img width="1440" alt="スクリーンショット 2020-03-12 15.41.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/e8211626-bc78-6f8f-0c88-4e646133a3ff.png">

次の画面ですが、少しややこしいです
一番上のチェックを外します
するとその上に了承するかどうかでてきますのでそれもチェック
（画像に写りませんでした）
あとは画像の通りにチェックと項目選択

<img width="1440" alt="スクリーンショット 2020-03-12 15.42.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/0976d6b4-0011-8c06-9120-b21b138c5680.png">

次へをクリックすると確認画面に移るので問題なかったらバゲット作成完了です

ルートユーザーでログインし直してIAMを検索
IAMユーザーの「ユーザーのARN」をコピー
<img width="1440" alt="スクリーンショット 2020-03-12 15.52.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/e5a0ce05-a011-3297-1343-50d081c69fdf.png">

そのままサービスでS3検索→作成したバゲットをクリック→「アクセス権限」→「バゲットポリシー」をクリック
<img width="1440" alt="スクリーンショット 2020-03-12 15.56.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/c4c90a21-02e1-aefe-30ad-0d231879ea09.png">

すると広いエディタのようなテキストフィールドが現れるので下記を自身の環境に合わせてコピー
①先ほどコピーしたIAMユーザーのARN
②バゲット名
に置き換えてください

```terminal:バゲットポリシー
{
    "Version": "2012-10-17",
    "Id": "Policy1544152951996",
    "Statement": [
        {
            "Sid": "Stmt1544152948221",
            "Effect": "Allow",
            "Principal": {
                "AWS": "************①****************"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::************②**********"
        }
    ]
}

```

これでS3の準備はできました
アプリの方の設定をしていきます
fog-awsというgemを導入します

```rails:Gemfile
gem 'fog-aws'
```
次にimagruploader.rbの設定を変更し、fogを使用するよう変更します

```rails:app/uploaders/image_uploader.rb
storage :fog
```

credentials.ymlにawsの公開鍵、秘密鍵を記述します
S3用のIAMユーザー作成時にダウンロードしたcredentials.csvをコピーして
それぞれコピペします

```rails:ローカルターミナル
EDITOR='code --wait' rails credentials:edit
# awsのコメントアウトを解除して編集
```


私はcarrierwaveという画像アップロードをするためのgemを使ってます
config/initializers直下にcarrierwave.rbというファイルを新規作成し、
下記をコピペしてください

```rails:config/initializers/carrierwave.rb
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_credentials = {
    provider: 'AWS',
    aws_access_key_id: Rails.application.credentials[:aws][:access_key_id],
    aws_secret_access_key: Rails.application.credentials[:aws][:secret_access_key],
    region: 'ap-northeast-1'
  }

  config.fog_directory  = 'ここにバケット名を入れます'
  config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/ここにバケット名を入れます'
end
```

deploy.rbの設定もmaster.keyを参照するように変更します

```rails:config/deploy.rb
# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '現在のcapistranoのバージョン'

# Capistranoのログの表示に利用する
set :application, 'アプリ名'

# どのリポジトリからアプリをpullするかを指定する
set :repo_url,  'git@github.com:Githubのユーザー名/リポジトリ名.git'

# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, 'アプリのRubyのバージョン' 

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['~/.ssh/pemの場所'] 

# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

#secrets.ymlではリリースバージョン間でシンボリックリンクにして共有
#credentials.yml.encではmasterkeyにする（今回）
set :linked_files, %w{config/master.key}

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do

  task :restart do
    invoke 'unicorn:restart'
  end

  desc 'upload master.key'
  task :upload do
    on roles(:app) do |host|
      if test "[ ! -d #{shared_path}/config ]"
        execute "mkdir -p #{shared_path}/config"
      end
      upload!('config/master.key', "#{shared_path}/config/master.key")
    end
  end
  before :starting, 'deploy:upload'
  after :finishing, 'deploy:cleanup'
end

```

これでGithubにプッシュし、自動デプロイを行えば完成です！

ありがとうございました