Amazon S3を利用した画像投稿や保存をする（パケットへ画像を保存する）

<br>初めて書きます！！　**Toshi**と申します。始めたばかりで駆け出しのエンジニア志望生です。<br>某プログラミングスクールで3ヶ月ほどカリキュラム基礎を学んで残りの3ヶ月で個人アプリの制作をしています。

Qiitaは自分の学びのストックと、もし同じ悩みを持った方の参考に少しでもなればと思い、不定期ですが更新していきたいと思っています！！<br>よろしくお願いします:blush:<br><br>
初投稿はタイトルの通りAmazon S3を利用しての画像保存について書いていきたいと思います。<br>(今回、学んだテキストからかなり引用気味です。。笑）


#　この記事の対象の方
>・AWSでIAMアカウントを登録している<br>・Ruby on railsを学んでいる方（他の言語でもS3は出てくるかとは思いますが、この後はRuby on railsが引き合いに出てくるため）<br>ActiveStorageを用いた画像保存などを知っている方<br>・Herokuをお使いの方

ただ、条件関係なくその他の方も全然Welcomeです:sunglasses:


#　そもそも「Amazon S3」とは

>「Amazon S3」はAWSの中のサービスの1つで、ネット上にデータを保存する箱を借りられるようなイメージです。<br>ここに画像などを保存したり、保存してある画像を取得したりすることができます。<br><br>「Amazon S3」を使うことで、データ容量を気にすることなく画像を保存することができます。S3に保存できるデータの量は膨大で、個人で作成するアプリで使われるレベルの量なら完全に無料で利用できます。

<br>ちなみに
>AWSへのアカウント登録で**無料期間が12ヶ月であったり上限があったり**で、従量課金制なので知らない間にお金がかかるかも知れませんので、ご注意を。。


#　STEP1 「S3で保存先を用意する」

準備前に「バケット」と「リージョン」を知っておく必要あります。

>バケット：データが格納される場所のこと<br>※英数字で誰もつけたことのない名前にする。
<br>リージョン：バケットが実際に存在しているサーバーの在り処。IPアドレスなどに近いイメージ。

まず、バケットを作成していきます。自身のアカウントのメニューバーにある「サービス」をクリックし、「S3」をクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/241ba9ec-fe50-494d-1780-86aab84c37af.png)


「バケットを作成」をクリックし、名前やリージョン「アジアパシフィック（東京）」を入力していきます。<br>
![スクリーンショット 2020-11-21 19.25.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/448562e1-e83d-67d1-0cd9-7328548eade0.png)
![スクリーンショット 2020-11-21 19.27.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/0b3b2fce-779e-67c1-dfed-dccbe622b930.png)

次に、セキュリティの設定をしていきます。「パブリックアクセスをすべてブロック」のチェックを外し、画像のようにチェックを入れていきます。<br>
![スクリーンショット 2020-11-21 19.29.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/73459c82-5fff-1fcb-f901-897e2239b43b.png)
![スクリーンショット 2020-11-21 19.32.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/83ccf4bc-5294-9bc5-6f35-fc23bfc1fb93.png)

その他は特にいじらずに、「バケットを作成」して作業は完了です。
![スクリーンショット 2020-11-21 19.33.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/7fa17d75-01f5-e47e-a91b-c62e8908758d.png)


#　STEP2 「バケットポリシーを設定する」
準備前に「バケットポリシー」を知っておく必要あります。

>バケットポリシー：どのようなアクセスに対してS3への保存やデータの読み取りを許可するか決められる仕組みです。

今回は、「IAMユーザー」からのアクセスだけが保存やデータの読み取りを許可するという設定にします。<br>※AWSで使えるサービスを制限しておくユーザー。アカウント乗っ取りや情報漏洩に対しセキュリティのため、通常はこちらのユーザーで作業します。<br>メニューバーのサービスをクリックし、検索画面で「IAM」と検索します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/2360e4c4-d2c2-6b39-ef61-5633182e3df7.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/7e6e25d3-d378-1911-4934-6e43a264ad3f.png)
<br>
「ユーザー」を選択します。<br>※画像引用上「先ほど」とありますが、すでに作成したものという認識でお願いいたします
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/309f4a18-c999-4783-c65a-93d608218c06.png)
<br>
IAMユーザーの情報が表示されますので、必要な情報を取得します。 後ほど「ユーザーのARN」が必要になりますので、一度メモアプリなどに保存しておきましょう。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/a3a70a4e-31e6-9db4-a715-454e45737416.png)
<br>
バケットポリシーの設定を行っていきます。サービス一覧から「S3」を選びます。先ほど作成したバケットをクリックします。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/496c0373-8470-6efc-03ca-73583c2f33f7.png)
<br>
アクセス権限（もしくはアクセス許可）をクリックすると、「パケットポリシー」を設定する箇所が出てきます。<br>（画像のように「パケットポリシー」をクリックかスクロール）<br>下の入力内容を参考に、パケットポリシーを入力します。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/21bed5d7-cf0b-287c-1133-3930e95d15e2.png)

```
{
   "Version": "2012-10-17",
   "Id": "Policy1544152951996",
   "Statement": [
       {
           "Sid": "Stmt1544152948221",
           "Effect": "Allow",
           "Principal": {
               "AWS": "①"
           },
           "Action": "s3:*",
           "Resource": "arn:aws:s3:::②"
       }
   ]
}
```

上記の①にはコピーしておいた「ユーザーのARN」を記載、②には作成したバケット名を入れましょう！<br>ここまでが、バケットポリシーを設定するになります。<br>
#　STEP3 「ローカル環境から、画像をS3のバケットに保存できるように設定する」
<br>※ここからはRuby on railsの話になります。
<br>Gemfileの一番下に下記を追記をします。「bundle install」も忘れずに。

```
gem "aws-sdk-s3", require: false
```
保存先を指定していきます。今回はローカル環境、すなわち開発環境であるため、「config/environments/development.rb」を編集していきます。<br>

```ruby:config/environments/development.rb

（省略）

config.active_storage.service = :local

（省略）
```

↓以下のように編集

```ruby:config/environments/development.rb

（省略）

config.active_storage.service = :amazon

（省略）
```
<br>
次に、config/storage.ymlを編集をします。

```ruby:config/environments/development.rb

（省略）

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: ご自身のバケット名をセット

（省略）
（省略）
```
<br>
環境変数を設定していきます。MacOSが「Catalina」以降を想定しています。

```ruby:ターミナル
% vim ~/.zshrc
```
<br>
「i」を押してインサートモードにしましょう。※既存のコードを消さないように注意！！

```ruby:ターミナル
export AWS_ACCESS_KEY_ID="ここにCSVファイルのAccess key IDの値をコピー"
export AWS_SECRET_ACCESS_KEY="ここにCSVファイルのSecret access keyの値をコピー"
```
※CSVファイルの「Access key ID」や「Secret access key」はIAMアカウントを作成時にダウンロードできます。IAMアカウントも別の記事で紹介できればと思います。。

<br>編集が完了したら「esc」キー→「:wq」の順で実行し保存します。<br>編集した「.bash」を読み込み直し、追加した環境変数を使えるように以下のコマンドを実行します。

```ruby:ターミナル
% source ~/.bash_profile
```
ただし、これだけではうまくいかない場合があるので、ターミナル再起動や「rails s」でサーバー再起動もお願いします。<br><br>これで完了です。既存のアプリで保存し、バケットで保存ファイルの有無を確認しましょう！！！
![9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/08cd43fb-1205-2633-cbeb-9cb36cc62f6a.gif)



#　STEP4 「本番環境から、画像をS3のバケットに保存できるように設定する」
<br>※ここからはHerokuを前提とした話になります。
<br>

保存先を指定していきます。今回は本番環境であるため、「config/environments/production.rb」を編集していきます。<br>

```ruby:config/environments/production.rb

（省略）

config.active_storage.service = :local

（省略）
```

↓以下のように編集

```ruby:config/environments/production.rb

（省略）

config.active_storage.service = :amazon

（省略）
```
<br>
次に、Heroku上で環境変数を設定します。ターミナルで下記のコマンドを実行します

```ruby:ターミナル（開発中のアプリのパスで実行）

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

% heroku config:set AWS_SECRET_ACCESS_KEY="ここにCSVファイルの「Secret access key」の値をコピー"
```
<br>
Heroku上で環境変数が正しく設定できているかを確認するために、下記のコマンドを入力します。

```ruby:ターミナル（開発中のアプリのパスで実行）

% heroku config
```
<br>以下のように出てくれば問題ありません。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759485/2ddba23e-fe81-693b-a7d3-89b24028e8d0.png)


herokuへコミットするため、GitHubのmasterブランチへマージして、下記のコマンドをターミナルで実行します。

```ruby:ターミナル（開発中のアプリのパスで実行）

% git push heroku master
```
<br>本番環境も正しく保存でき、S3で保存が確認できれば完了です！！


#最後に

Ruby on rails、herokuと縛りがあるため、お役に立たなかったかも知れませんが、少しでも参考になれば幸いです。 今後も発信していければと思います！