[AWS]S3への画像の保存

# はじめに
herokuにアプリケーションをデプロイしましたが、画像ファイルがリンク切れになるため、S3に保存先を設定しました。

# 目次
1.バケットの作成
2.バケットポリシーの設定
3.画像がS3のバケットに保存されるように設定

# 1. バケットの作成
バケットとはS3で実際にデータが格納される場所のことです。
上部の「サービス」をクリックして、「S3」をクリックします。
![](https://i.gyazo.com/56909885591bd976de55fbe8cf2c53e0.png)
ページ遷移したら、「バケットを作成」をクリックします。

次に「バケット名」を入力します。
**「バケット名」は他のユーザーが作ったバケットと重複した名称は使うことができません。**
「リージョン」は「アジアパシフィック（東京）」を選択しておきましょう。
![](https://i.gyazo.com/9e6e92e10d68b97000e7edb4c33086f9.png)
遷移後の画面では何も選択せずに「次へ」をクリックします。

「パブリックアクセスをすべてブロック」のチェックを外します。
以下のように3箇所にチェックを入れ、「次へ」をクリックします。
![](https://i.gyazo.com/098c8abc9c178b4448be4a1d2c85336f.png)
画面遷移後、バケット作成の内容を確認し問題がなければ「バケットを作成」をクリックします。

# 2. バケットポリシーの設定
バケットポリシーとは、どのようなアクセスに対してS3への保存やデータの読み取りを許可するか決められる仕組みです。
今回は「IAMユーザー」からのアクセスのみを許可するように設定します。

まず、「IAMユーザー」の設定を確認します。
「サービス」をクリックし、「IAM」を検索します。
画面遷移後、「ユーザー」をクリックし、作成したユーザー名をクリックします。
ユーザーの情報が表示されるので、「ユーザーARN」をメモして保存しておきます。

次に、バケットポリシーの設定を行います。
先ほどと同様に「ユーザー」をクリックし、「S3」を検索します。
作成したバケットをクリックします。
「アクセス権限」をクリックし、「バケットポリシー」をクリックします。
![](https://i.gyazo.com/ff4c102ddb64df2e1bf4749ef8a67d0b.png)
バケットポリシーエディターに以下を貼り付けます。

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

先ほど保存しておいた**「ユーザーARN」を①**に、**「作成したバケット名」を②**に記述します。
「保存」をクリックし、「このバケットに対してパブリックアクセスの〜」と表示されていれば成功です。

# 3. 画像がS3のバケットに保存されるように設定
## ローカル環境からS3に画像を保存
### 必要なgemをインストール
S3を使用するために必要なgemをインストールします。
以下をgemfileの一番下に記述したらコマンドで**bundle install**を実行します。

```ruby:gemfile
gem "aws-sdk-s3", require: false
```

### 保存先を指定
現状画像の保存先はローカルに設定されているので、S3に保存されるように設定を変更します。
**「:local」→「:amazon」**に編集します。

```ruby:config/environments/development.rb
~略~
config.active_storage.service = :amazon
~略~
```

```ruby:config/storage.yml
test:
 service: Disk
 root: <%= Rails.root.join("tmp/storage") %>

local:
 service: Disk
 root: <%= Rails.root.join("storage") %>

# 以下を追記します
amazon:
 service: S3
 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
 secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
 region: ap-northeast-1
 bucket: ご自身のバケット名
~略~
```

「access_key_id」と「secret_access_key」は環境変数を読み込むための記述です。

### 環境変数の設定
ターミナルで以下のコマンドを実行します。

##### ターミナル
```
vim ~/.zshrc
```

「i」を押します。

##### ターミナル
```
export AWS_ACCESS_KEY_ID="ここにCSVファイルのAccess key IDの値をコピー"
export AWS_SECRET_ACCESS_KEY="ここにCSVファイルのSecret access keyの値をコピー"
```

「escキー」→「:wq」の順で実行します。

ターミナルで以下を実行し、設定を反映させます。

##### ターミナル
```
source ~/.zshrc
```

アプリケーションを操作し、S3に画像が保存されているか確認します。

## 本番環境（Heroku）からS3に画像を保存
### 保存先を指定
**「:local」→「:amazon」**に編集します。

```ruby:config/environments/production.rb
~略~
config.active_storage.service = :amazon
~略~
```

### Heroku上で環境変数を設定
ターミナルで以下を実行します。

##### ターミナル
```
heroku config:set AWS_ACCESS_KEY_ID="ここにCSVファイルの「Access key ID」の値をコピー"
```

##### ターミナル
```
heroku config:set AWS_SECRET_ACCESS_KEY="ここにCSVファイルの「Secret access key」の値をコピー"
```

「heroku config」コマンドで環境変数を確認します。

### 編集内容をHerokuに反映
変更をmasterブランチにマージします。
下記のコマンドで編集した内容をHerokuに反映させます。

##### ターミナル
```
git push heroku master
```

以下のコマンドを実行し、「Web URL」にアクセスしS3に画像が保存されるか確認します。

##### ターミナル
```
heroku apps:info
```