2013年2月28日木曜日

Railsのassetsをs3に格納し、cloudfrontから配信する


今まで使おう使おうと思いつつ、さほどPVがあるサイトの運営をする機会がなかったため、
やってなかったcloudfrontを満を持して設定してみました。
(とりあえず入れとけ的な話もよく聞きますし…)

今回は、railsのassetsをS3に置いて、cloudfrontから配信するようにしました。
結果、噂通りすごく簡単に導入できたのですが、調査に割りと時間がかかったのでメモしておきます。

Herokuのドキュメントを取っ掛かりにしました。



概要は以下です。

  • assets格納用のS3バケットを作る
  • cloudfrontのdistributionを作成し、S3をorigin serverに設定
  • railsプロジェクトに設定追加
    • Gemfileに、gem "asset_sync" を追加
    • config/initializersに、asset_sync.rb を作成 (カスタム設定の場合)
    • config/environments/production.rbに、asset_host を設定
  • assets:precompile を実施

これだけ、すごく簡単でした。




まずは、S3のバケット作成。 これはcloudfrontを使う方には、特に説明不要と思うので省略。




次に、cloudfrontのdistribution設定。 こちらも、 公式ドキュメントを見ればOKかと思います




で、メインのrailsの設定です。

・Gemfileに、gem "asset_sync"を追加
これはそのままです。bundle install すればOK。


・config/initializersに、asset_sync.rb を作成。
https://github.com/rumblelabs/asset_sync のReadmeを参考に設定。(ymlで設定する例の記載もあります)

まずはrailsコマンドで設定ファイルのテンプレートを作成。
環境変数を使用することで作らなくても使用出来るようですが、個人的に設定ファイルが
あったほうが安心するタイプなので、今回は作りました。

$ rails g asset_sync:install --provider=AWS

下記のような形で自分好みに設定。

AssetSync.configure do |config|
config.fog_provider = 'AWS'
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
config.fog_directory = ENV['FOG_DIRECTORY'] # S3 Bucket name
config.fog_region = ENV["AWS_DEFAULT_REGION"] || 'ap-northeast-1'
config.enabled = true
# config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
# config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
# config.fog_directory = ENV['FOG_DIRECTORY']
# Increase upload performance by configuring your region
# config.fog_region = 'eu-west-1'
#
# Don't delete files from the store
# config.existing_remote_files = "keep"
#
# Automatically replace files with their equivalent gzip compressed version
# config.gzip_compression = true
#
# Use the Rails generated 'manifest.yml' file to produce the list of files to
# upload instead of searching the assets directory.
# config.manifest = true
#
# Fail silently. Useful for environments such as Heroku
# config.fail_silently = true
end
view raw asset_sync.rb hosted with ❤ by GitHub

・config/environments/production.rbに、asset_host を設定
以下の通り。

  # Enable serving of images, stylesheets, and JavaScripts from an asset server   
  config.action_controller.asset_host = "//YOUR_CLOUDFRONT_ENDPOINT" 

'//' から始まっているのが変な感じがしますが、こうしておくとアクセスされたプロトコル
(HTTPなら http://YOUR_CLOUDFRONT_ENDPOINT、 HTTPSなら https://YOUR_CLOUDFRONT_ENDPOINT)
でcloudfrontにもリクエストするとのこと。




asset_syncの準備が出来たので、
bundle exec rake assets:precompile RAILS_ENV=production とかやると…

AssetSync: using config/initializers/asset_sync.rb
AssetSync: Syncing.

Uploading: assets/application-55f294e47fb7ed0b383b882262f9820d.js.gz

Uploading: assets/application-55f294e47fb7ed0b383b882262f9820d.js
AssetSync: Done.

という感じでS3にアップロードされるので、あとはCloudfrontがよしなにキャッシュしてくれます。




最後に、Rails を起動してアクセスすれば、cloudfrontからassetsを取得してることが分かると思います。




以上です。 思ってたよりもすごく簡単に出来ました。

キャッシュというとexpireをどうするか的な問題がもれなくついてくると思いますが、
railsはデフォルトで、ファイル名にハッシュをつけてくれるので問題ないようです。

ハッシュ値自体もファイルの中身から算出するとのことなので、stagingとかproductionとか
いくつか環境があっても共有できます。嬉しい。

また、assets_sync自体も既にS3にあるファイルはアップロードしないので、
余計な時間がかかることもありません。嬉しい。

AWS と rails という巨人と、その他素晴らしい先人達の肩にしがみつくと、自分もなんとか生きていける気がしました。


おしまい。

↓参考になります。

0 件のコメント:

コメントを投稿