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'] %>
  • .envファイルで環境変数を設定
  • これでAWSでgit pullし、本番環境で画像投稿すれば、S3のバケットに画像が保存されるようになっている

参考(誤操作で秘密情報をpushしないよう対策)

git-secretsを設定して、セキュリティー対策

  • ターミナルから、Homebrewを経由してgit-secretsを導入

ターミナル

% cd ~/ #ホームディレクトリに移動
% brew install git-secrets
  • git-secretsが導入できたら、設定を適用したいアプリケーションのディレクトリに移動して、git-secretsを有効化

ターミナル

% cd アプリケーション名 #開発中のアプリに移動
% git secrets --install
  • 続いて、どのようなコードのcommitを防ぐのかを設定→「Access key ID」「Secret access key」等、アップロードしたくないAWS関連の秘密情報を一括で設定

ターミナル

% git secrets --register-aws --global
  • 実際にどのような設定がされているか確認

ターミナル

% git secrets --list
  • これで、「git secrets --install」を行なったリポジトリでは「git commit」コマンドを実行した際にAWSの秘密情報を含んでいないかチェックされるようになった

GitHub Desktopを利用している場合

  • GitHub Desktopがアプリケーションのディレクトリに存在しているか確認
  • 以下のコマンドを実行してGitHub Desktopにgit-secretsを適用

ターミナル

% 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のドメイン名を記述→ルーティングポリシーはシンプルで→「レコードを作成」

手順4 Rials側で設定