AWSのS3で画像を配信
内容
画像の保存にAWSのS3を使用する
基礎知識
- S3
→安価で耐久性の高いAWSのクラウドストレージサービス
→静的コンテンツの配信やバッチ連携用のファイル置き場、ログ等の出力先、静的ウェブホスティング等で利用する - git-secrets
→AWSが公開しているツールで、commitしようとしたコードをチェックし、パスワードだと推定されるような文字列が含まれている場合は、警告を出して処理が中断してくれる機能 - CloudFront
→高速にコンテンツを配信するサービス(CDNのサービス)
→CloudFrontがあることで、高速化され、S3の負荷が軽減される
→高速(ユーザーから最も近いエッジサーバーから画像を配信する)で、効率的(エッジサーバーでコンテンツのキャッシングを行うので、オリジンサーバーに負荷をかけずに配信できる) - CDN(Content Delivery Network)
→オリジンサーバー(元となる画像を配信するサーバー)上にあるコンテンツを、世界中100箇所以上にあるエッジロケーションにコピーし、そこから配信を行う
S3に画像を保存
手順1 バケットの作成
手順2 セキュリティ対策
- IAMのユーザー→作成済みのIAMユーザーをクリック
- 概要のユーザーARNをコピー
- バケットポリシーを設定するため、S3のバケットを開き、作成したバケットをクリック
- アクセス許可→バケットポリシーの編集→以下のように編集
バケットポリシー
{ "Version": "2012-10-17", "Id": "Policy1544152951996", "Statement": [ { "Sid": "Stmt1544152948221", "Effect": "Allow", "Principal": { "AWS": "①" }, "Action": "s3:*", "Resource": "arn:aws:s3:::②" } ] }
- 「①」の箇所に、先ほどコピーした「ユーザーのARN」を入力
- 「②」の箇所に、作成したバケット名を入力
手順3 本番環境からS3に画像を保存
- S3を使用するために必要なGemfileを導入(Gemfileの一番下に以下を追記)
Gemfile
gem "aws-sdk-s3", require: false
ターミナル
% bundle install
- 画像の保存先を指定するために、production.rbを編集
※現状では画像の保存先が「local」に設定されており、アプリケーション内に画像を保存することを意味しているので、S3に保存されるように設定を変更
config/environments/production.rb.rb
# 元々 config.active_storage.service = :local # 以下のように変更 config.active_storage.service = :amazon
- storage.ymlに以下のコードを追記
config/storage.yml
test: # 省略 lacal: # 省略 amazon: service: S3 region: リージョン名(例:ap-northeast-1 bucket: バケット名 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
参考(誤操作で秘密情報をpushしないよう対策)
git-secretsを設定して、セキュリティー対策
- ターミナルから、Homebrewを経由してgit-secretsを導入
ターミナル
% cd ~/ #ホームディレクトリに移動 % brew install git-secrets
- git-secretsが導入できたら、設定を適用したいアプリケーションのディレクトリに移動して、git-secretsを有効化
ターミナル
% cd アプリケーション名 #開発中のアプリに移動 % git secrets --install
ターミナル
% git secrets --register-aws --global
- 実際にどのような設定がされているか確認
ターミナル
% git secrets --list
GitHub Desktopを利用している場合
ターミナル
% sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets # 上記コマンドで「No such file or directory」のエラーがでる場合はGitHub Desktopのバージョンが古い可能性があるので、以下のコマンドを実行 % sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/git/bin/git-secrets
※パスワードは自身のPCにログインする際のパスワード
- 今後作成する全てのリポジトリに、git-secretsが適用されるようにする
ターミナル
% git secrets --install ~/.git-templates/git-secrets % git config --global init.templatedir '~/.git-templates/git-secrets'
CloudFrontを利用して画像を高速配信
手順1 CloudFrontを設定
- CloudFrontのディストリビューションの作成をクリック
- オリジン→オリジンドメインはS3で作成したキャッシュさせたいバケット、オリジンパスは今回は空(指定したディレクトリのみキャッシュさせたい場合は指定)、名前はそのまま、S3バケットアクセスは今回はNoのまま(Cloud Frontのみにアクセスさせたい場合は「Yes」を選択)、オリジンシールドはNoのまま
- Default Cache Behavior→特にいじる必要なし
- 設定→すべてのエッジロケーションを使用するが設定されていればOK→ディストリビューションを作成
手順2 CloudFrontではなく独自ドメインで画像が配信されるように設定
- 作成したCloudFrontのIDをクリック→一般の設定の編集をクリック
- 代替ドメイン名(CNAME)→項目を追加→今回は「static.ドメイン名」というサブドメイン名で配信
- SSL証明書を取得するために「証明書をリクエスト」をクリック
- ドメイン名の追加→「*.myapp.com」「myapp.com」等のように、サブドメイン全てを許容するものとドメイン本体を追加しておく→「次へ」
- DNSの検証→「次へ」
- タグの追加は特に必要ないので「確認」
- 確認して「確定とリクエスト」
- ドメイン名横の三角ボタンを押し、「Route 53でのレコードの作成」→「作成」をクリックして「続行」
- 「SSL証明書」が発行されるまで待ち、発行されたら準備完了
- CloudFrontの画面に戻る→カスタムSSL証明書→*付きのドメイン名を選択→他はそのままで「変更を保存」
手順3 Route 53で独自ドメインとCloudFrontの紐付け
- Route 53のホストゾーンでドメイン名を選択→レコードを作成→レコード名「static」を追加、レコードタイプは「CNAME」、値はCloudFrontのドメイン名を記述→ルーティングポリシーはシンプルで→「レコードを作成」