こんにちは。Enjoy IT Life管理人の仁科(@nishina555)です。
Railsアプリケーションで利用されるアセットファイルは、デフォルトの設定ではアプリケーションサーバに配置されています。
今回はアセットファイルを外部リソースへ配置し、配信できるようにするasset_syncgemの使い方について紹介します。
asset_syncを導入するメリットは以下の2点です。
- アセットファイルを参照する際にアプリケーションサーバーへアクセスする必要がなくなるため、サーバー負荷を軽減できる
- CDNを利用することでキャッシュを活用した高速な配信が可能になる
今回利用する検証環境の詳細は以下の通りです。
- ストレージ: S3
- CDN: CloudFront
- asset_syncのバーション: 2.12.1
- railsのバージョン: 6.0.3.2
- Railsの実行環境: 本番(production)
目次
下準備: サンプル画像を表するRailsアプリケーションの作成
アセットファイルの配信元が変更されているか検証するためにサンプルアプリケーションを作成します。
app/assets/images
配下に適当なイメージ画像を配置します。今回はgroup_young_world.png
というサンプル画像を用意しました。
ルーティングの編集をします。
config/routes
Rails.application.routes.draw do
+ root to: 'home#index'
end
トップページを表示するコントーラー・ビューを作成します。
$ bundle exec rails g controller home index
app/views/home/index.html.erb
<%= image_tag 'group_young_world.png', width: '500' %>
assets:precompile
を実行とアプリケーションの起動をします。
$ bundle exec rails assets:precompile RAILS_ENV=production
$ bundle exec rails s -e production
トップページを表示するとサンプル画像が表示されます。ソースコードを確認するとassets
配下のファイルを直接参照していることがわかります。
S3バケットを作成する
S3のダッシュボードの『バケットを作成する』を選択します。
必要項目を入力してバケットを作成します。
Webサイトを公開状態にするため、アクセス許可の設定で『パブリックアクセスをブロック』のチェックを外します。
一覧にS3バケットが表示されればOKです。
Railsアプリケーションの修正
Gemのインストールをします。fog-awsはAWS連携に必要なクラウドサービスライブラリです。
Gemfile
gem 'asset_sync'
gem 'fog-aws'
asset_syncのinitializerのインストールと設定を行います。
$ bundle exec rails g asset_sync:install --provider=AWS
config/initializers/asset_sync.rb
if defined?(AssetSync)
AssetSync.configure do |config|
config.fog_provider = 'AWS'
config.fog_directory = 'rails-app-production-assets' # S3バケット名
config.aws_access_key_id = 'xxx' # IAMユーザのアクセスキー
config.aws_secret_access_key = 'xxx' # IAMユーザのシークレットキー
config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.key?('AWS_SESSION_TOKEN')
config.fog_region = 'ap-northeast-1' # S3バケットのリージョン
end
end
IAMユーザーにはS3のアクセス権限が必要です。必要に応じてAWSのIAMコンソールで新規ユーザーの作成、もしくは既存ユーザーへの権限付与を行ってください。
なお、今回は説明の都合上、設定ファイルに直接アクセスキー・シークレットキーを記載しています。
実際の運用では、秘匿情報はシェルの設定ファイルやdotenv-railsを活用して環境変数でセットすることをオススメします。
Railsの設定ファイルを修正します。今回は本番環境で実行するためenvironments/production.rb
を編集します。
config/environments/production.rb
Rails.application.configure do
+ config.action_controller.asset_host = "http://rails-app-production-assets.s3.amazonaws.com" # S3バケットのエンドポイント
end
設定が完了したらRailsアプリケーションを起動します。
$ bundle exec rails assets:precompile RAILS_ENV=production
$ bundle exec rails s -e production
ソースコードを確認するとS3バケットにアクセスしてファイルを表示していることがわかります。
S3バケットにはassets
ディレクトリが同期されています。
CloudFrontを導入し、アセットファイルをキャッシュできるようにする
CloudFrontとはコンテンツ配信ネットワークサービスを提供するAWSの機能です。
コンテンツ配信ネットワークサービスは総称してCDNと呼ばれています。つまり、CloudFrontはCDNの一種といえます。
CDNにはコンテンツのキャッシュ機能が搭載されています。
CloudFrontを利用することでアセットファイルをキャッシュできるため、ファイルアクセスの高速化の効果が期待できます。
CloudFront経由でS3バケットへアクセスできるように設定をします。
CloudFrontのダッシュボードを開き、『Create Distribution』を選択します。
Webの『Get Started』を選択します。
『Origin Domain Name』は、『Amazon S3 Buckets』に表示されているS3バケットのエンドポイント(xxx.s3.amazonaws.com
)を指定します。
そのほかの設定はデフォルトで指定されているものを選択します。
設定に問題がなければ、設定完了後しばらくするとステータスが『Deployed』になります。
アセットファイルのアクセスポイントが変わったのでRailsの設定ファイルを変更します。
config/environments/production.rb
Rails.application.configure do
- config.action_controller.asset_host = "http://rails-app-production-assets.s3.amazonaws.com" # S3バケットのエンドポイント
+ config.action_controller.asset_host = "https://d8yldxafmxvy8.cloudfront.net" # CloudFrontのドメイン名
end
CloudFrontのドメイン名は一覧画面から確認できます。
Railsアプリケーションの再起動後、ソースコードを確認するとCloudFront経由でファイルを表示していることがわかります。
今回はCloudFrontのドメイン名をアセットファイルのホストにしましたが、CloudFrontのドメイン名に独自ドメインを割り当てることも可能です。
CloudFrontに独自ドメインを割り当てる手順についてはhttps対応した独自ドメインのWebサイトをS3 + CloudFrontで運用する手順を参考にしてください。
まとめ
以上で、S3 + CloudFrontを活用したRailsアプリケーションのアセットファイル配信方法の紹介を終わります。
- asset_syncを利用することで外部リソースからアセットファイルを配信できる
- CloudFrontを活用することでファイルアクセスの高速化が期待できる
今回の検証結果を見てわかるように、S3に配置されるアセットファイルはassets
ディレクトリのみで、Webpackerでビルドされたファイルの出力先であるpacks
は含まれていません。
asset_syncのWebpacker対応は【Rails】asset_syncでWebpackerのビルドファイルをS3に同期する手順で紹介しているので参照してください。
この記事がいいなと思いましたらTwitter(@nishina555)のフォローもよろしくお願いします!