LoginSignup
5
16

More than 3 years have passed since last update.

AWSに画像をアップロードする

Posted at

Heroku上で扱う画像ファイルなどは、アプリがデプロイされるか、
アプリが再起動(24時間に1回自動で行われる)される度に消えてしまう仕様です。

なので、アップロードされた画像を「AWS」というサービスに保存されるようにする事で
この問題を解決していきたいと思います。

目次

①.AWSアカウントの作成
②.AWS上のセキュリティ対策
③.S3でバケット(保存先)を作成
④.画像がS3のバケットに保存されるように設定


それでは早速始めていきます!

①AWSアカウントの作成

https://aws.amazon.com/jp/
にアクセスしてサインアップします。
注意点は、アカウントの種類は「パーソナル」を選択すること。
サポートプランは無料のベーシックプランでOK
ここまできたら、実際にサインインして確認します。

②AWS上のセキュリティ対策

3つの設定を行います。

1.二段階認証の設定
2.IAMユーザーの作成
3.git-secretsの利用

1.二段階認証の設定

Authyというアプリケーションを利用するので、
ますは「Authy」を自分のスマホにインストールします。
初期設定が終われば、次はAWSマネジメントコンソールにアクセスします。

ヘッダーからアカウント名をクリックし、メニューの中から 「マイセキュリティ資格情報」 を選択
Image from Gyazo

モーダル画面が表示されたら「Continue to Security Credentials」 をクリック。

メニューの中の 「多要素認証(MFA)」 をクリックすると内容が展開されるので、「MFAの有効化」 をクリック
Image from Gyazo

モーダル画面の中から「仮想MFAデバイス」が選択されているのを確認して、続行をクリック
→次の画面で「QRコードの表示」をクリックすると、QRコードが表示されます。
→この状態で先ほどの「Authy」アプリを起動し、「Accounts」にある「+」ボタンをタップ
→設定画面を終了すると、二段階認証用のパスワードが表示されるようになります。

ワンタイムパスワードなので、30秒経つと自動的にそのパスワードは無効になります。
このパスワードをAWSで入力します。

1つ目のパスワードを上の欄に、その次に表示されたパスワードを下の欄に入力
最後に「MFAの割り当て」をクリックして設定は完了


2.IAMユーザーの作成

IAMユーザーとは、AWSのサービスの1つで、機能を制限したユーザーを作成できる機能のこと
※最初にAWSで作ったアカウントはルートユーザー

検索のフォームに「IAM」と打ち込み、出てきた検索結果からIAMのページに飛ぶ
Image from Gyazo

遷移先のページで個々の「IAMユーザーの作成」をクリックし、「ユーザーの管理」をクリック
Image from Gyazo

遷移先のページで「ユーザーを追加」をクリックすると下記の画面になりますので、
作成するユーザー名の入力と、「プログラムによるアクセス」にチェック
そのあとは右下の「次のステップ:アクセス権限」をクリックして進みます。
Image from Gyazo

「既存のポリシーを直接アタッチ」から検索窓に「amazons3」と入力し、
「AmazonS3FullAccess」に設定後、右下の「次のステップ:タグ」をクリック
Image from Gyazo

遷移後は何もせず「次のステップ: 確認」をクリック
最後に設定の確認をして、「ユーザーの作成」をクリック

これで「IAMユーザー」の作成が完了です。
最後に、忘れずに認証情報(.csv)をダウンロードしておきます。


「IAMユーザーのパスワード」を設定

IAMのメニューから作成したIAMユーザーをクリック
→「認証情報」のタブをクリックすると以下のページに遷移するのでコンソールのパスワード欄の「管理」 をクリック
Image from Gyazo

「有効化」「自動生成パスワード」をクリック
Image from Gyazo

ルートユーザーの時と同じく、認証情報はダウンロードしておきます。


作成したIAMユーザーでログイン

今作成したIAMユーザーでログインできることを確認してみます。
まずルートアカウントのサインアウトを行います。
Image from Gyazo

続いて、先ほどダウンロードしたcredential.csvを開くと下記の情報が記載されている

User name
Password
Console login link

User name と Password を入力して、Console login link のURLにアクセス

その後の画面で正常にログインできれば成功です。


ルートユーザーで再度サインイン

サインイン画面で「ルートユーザーのEメールを使用したサインイン」を選択。
二段階認証を経てログインできます。


IAMユーザーも二段階認証に

IAMのユーザー選択画面から先ほど作成したユーザー名を選択し、
遷移したページ先で以下の「MFAデバイスの割当」をクリック
Image from Gyazo

あとは ルートユーザーの時と同じ手順で二段階認証の設定を行う。


3.git-secretsの利用

「git-secrets」は、誤操作でパスワードをGitHubにpushしてしまう防いでくれるツールです。

まずはターミナルから、Homebrewを経由してgit-secretsを導入。

% cd ~/
% brew install git-secrets

git-secretsが導入できたら、設定を適用したいリポジトリに移動し、git-secretsを有効化

% cd アプリケーション名 #開発中のアプリケーションディレクトリに移動
% git secrets --install

続いて、「どのようなコードのコミットを防ぐのか」を設定していきます。
この後の作業は開発中アプリケーションのディレクトリで実行します。


git-secretsの条件を設定

下記のコマンドを実行することで、secret_key, access_keyなど、
アップロードしたくないAWS関連の秘密情報を一括で設定することができる

% git secrets --register-aws --global

現在のgit-secretsの設定は、下記のコマンドで確認することができる

% git secrets --list

secrets.providers git secrets --aws-provider
secrets.patterns [A-Z0-9]{20}
secrets.patterns ("|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)("|')?\s*(:|=>|=)\s*("|')?[A-Za-z0-9/\+=]{40}("|')?
secrets.patterns ("|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?("|')?\s*(:|=>|=)\s*("|')?[0-9]{4}\-?[0-9]{4}\-?[0-9]{4}("|')?
secrets.allowed AKIAIOSFODNN7EXAMPLE
secrets.allowed wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

これで、「git secrets --install」を行なったリポジトリでは、
コミット時にAWSの秘密情報を含んだコードがないかチェックされるようになりました。
「うっかりパスワードをGitHubに載せてしまった」という事態を防ぐことができるので、必ず設定を行う。


今後作成する全てのリポジトリにgit-secretsが適用されるように設定

特段の理由がなければ、以下のコマンドを実行して自動で適用されるようにしておく。

% git secrets --install ~/.git-templates/git-secrets
% git config --global init.templatedir '~/.git-templates/git-secrets'

GitHub Desktopからgit-secretsを利用できるように設定

GitHub Desktop経由でgit secretsを利用する場合は、追加の設定をします。
この時、Github Desktopがapplicationフォルダに存在している必要があ流ので適宜移動しておく。

以下を実行

% sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets

上記コマンドで「No such file or directory」のエラーがでる場合は以下のコマンドを実行

% sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/git/bin/git-secrets

③S3を利用してバケットを作成

S3で実際にデータが格納される場所のことを「バケット」と呼びます。
バケットの名前はアクセスするときのURLに使用されるため、
英数字で、まだ誰も付けたことがない名前を使う必要がある。

「ストレージ」のS3をクリック
Image from Gyazo

遷移後の画面で「バケットを作成」をクリックし、バケット名の入力とリージョンを設定。
リージョンは「アジアパシフィック(東京)ap-northeast-1」 を選択し「次へ」
Image from Gyazo

次の画面ではそのまま「次へ」

遷移後の画面で、「パブリックアクセスをすべてブロック」のチェックを外し、
新規の〜、任意の〜 にチェックを入れ、最後に上段のオレンジ色の注意喚起箇所のチェックを入れる。
「次へ」を選択し「バケットを作成」で完了です。
Image from Gyazo


バケットポリシー

どのようなアクセスに対してS3への保存やデータの読み取りを許可するか決められる仕組み。
今回は、作成したIAMユーザーからのアクセスのみを許可するように設定します。

AWSのトップページから「IAM」と検索し、表示されたメニューをクリック

「ユーザー」を選択し、「ユーザー名」のところの先ほど作成したユーザー名をクリック
Image from Gyazo

IAMユーザーの情報が表示されるので、必要な情報を取得。
後ほど「ユーザーのARN」が必要にるので、一度メモアプリなどに保存しておきます。

次に、バケットポリシーの設定を行います。
IAMの時と同じようにサービス一覧からS3を選びます。先ほど作成したバケットをクリック。

「アクセス権限」をクリックし、「バケットポリシー」をクリック
表示されるコード記述欄にポリシーの入力をします。
先ほどメモしておいた 「ユーザーのARN」を①に、「作成したバケット名」を②に記述します。

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

書けたら右上の「保存」をクリック
※保存ボタンを押した直後に「このバケットに対してパブリックアクセスの〜」と出ていれば保存成功。


④画像がS3のバケットに保存されるように設定

1.投稿機能の挙動確認
2.ローカル環境の画像保存先をS3に変更
3.本番環境の画像保存先をS3に変更

1.投稿機能の挙動確認

下記2点ができていることを確認します。
・ローカル環境で画像投稿が出来る
・画像がデータベースに保存されている

2.ローカル環境の画像保存先をS3に変更

以下の要領で進めていきます。

a.必要なGemをインストール
b.保存先を指定
c.環境変数を設定
d.正しく保存できるか確認

a.必要なGemをインストール

下記Gemを追記し、bundle install

gem "aws-sdk-s3", require: false

b.保存先を指定

development.rbを編集します。
画像の保存先を「:local」→「:amazon」に変更

config/environments/development.rb

config.active_storage.service = :local ←修正前
config.active_storage.service = :amazon ←修正後

storage.ymlを編集します。

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: <%= ENV['AWS_ACCESS_KEY_ID'] %>」「secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>」 

の部分は環境変数を読み込むための記述です。

c.環境変数を設定

【MacOSがCatalina以降の場合】
ターミナルで以下のコマンド実行

 vim ~/.zshrc

「i」を打ち込みインサートモードへ。下記のコードを貼り付けます。

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

完了したら、「escキー」→「:wq」の順で実行し、保存。
編集後は「.zshrc」を読み込み直す。

% source ~/.zshrc

【MacOSがMojave以前の場合】
ターミナルで以下のコマンド実行

 vim ~/.bash_profile

「i」を打ち込みインサートモードへ。下記のコードを貼り付けます。

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

完了したら、「escキー」→「:wq」の順で実行し、保存。
編集後は「.zshrc」を読み込み直す。

$ source ~/.bash_profile

d.正しく保存出来るか確認

ローカル環境で開発中のアプリから画像投稿を行い、S3に保存されているか確認してください。
バケット名をクリックすると投稿した画像があるはずなので、投稿日時を確かめ、今投稿した画像であることを確認します。

3.本番環境の画像保存先をS3に変更

以下の要領で進めます。

a.保存先を指定
b.Heroku上で環境変数を設定
c.正しく保存できるか確認

a.保存先を指定

本番環境の設定ファイルを開き、画像がS3に保存されるように設定を変更します。

production.rbを編集

config/environments/production.rb
config.active_storage.service = :local  ←修正前
config.active_storage.service = :amazon ←修正後

b.Heroku上で環境変数を設定

Herokuで環境変数を扱うにはマスターキーの時と同様、「heroku config:setコマンド」を打つ必要がある。

ターミナル(開発中のアプリ)で実行

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

環境変数が正しく設定できているかを確認するためにターミナル(開発中のアプリ)で下記のコマンドを入力

% heroku config

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY

がそれぞれ設定されていたら成功。
編集内容をコミット。(ブランチを切っている場合は必ずmasterブランチにマージする)
ターミナル(開発中のアプリ)で下記のコマンドを実行し、編集した内容をHerokuに反映。

% git push heroku master

このコマンドにより、herokuがリモートリポジトリのmasterブランチを参照することが出来る。

c.正しく保存できるか確認

本番環境で、開発中のアプリから画像投稿を行います。
そのためには以下の方法で「Web URL」を確認する必要がある。

以下のコマンドをターミナル(開発中のアプリ)で実行することで、
Herokuにデプロイされたアプリケーションの情報を見ることができる。

% heroku apps:info

「Web URL: 〜」の部分を確認できたら公開されたページにアクセスし、画像投稿をします。
その後、AWSトップページからS3にアクセスし、バケットにファイルが保存されているか確認します。

バケット名をクリックすると投稿した画像があるはずなので、投稿日時を確かめ、今投稿した画像であることを確認します。


以上です。お疲れ様でした。

5
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
16