AmazonCloudFrontでRailsのAssets周りにある静的ファイルをCDN配信する
AmazonCloudFrontでRailsのAssets周りにある静的ファイルをCDN配信する
RailsでアプリのassetsをCloudFront経由で配信した時の話
問題と解決
Railsのアクションキャッシュ導入時、Webサーバ内からassetsの配信を行っていた。
その場合、Deploy時にassets precompile
を実行しmanifestの更新を行うと、
キャッシュしていたviewのCSSがmanifest更新に伴って参照できなくなり、表示が崩れてしまうという問題が発生した。
この問題を解決するために、Deploy時にassets以下のファイルをS3に置いてCloudFront経由で配信する形式に変更することにした。
CDN
CDN (コンテンツデリバリーネットワーク) Akamaiが1990年代に提唱したコンテンツを配信するネットワーク
参考: 第1回 CDN の 仕組み (CDNはどんな技術で何が出来るのか)
Amazon CloudFront
AWSが提供するCDNサービス 今回はCloudFrontを使いました
Amazon S3
SimpleStrageService Sが3つでS3 「超便利ファイル置き場」
今回は静的ファイルをS3に置いてCloudFrontが参照する
CDNを導入すると何が良いの?
パフォーマンスが良くなる。(高速化) 世界中のどこからアクセスされてもある程度一定のレスポンス速度を担保できる。
やること
- S3バケットを用意
- CloudFront側の設定
- Rails側の設定
- sprocketsのmanifestファイル
- S3でクロスオリジンの設定
S3バケットを用意
assetsファイルはS3バケットに置くので、バケットを用意します
assets.service-domain.com
CloudFrontの設定
CIでprecompileを行いS3にファイルを置く
DeployフローでCIを通す前提の話です。普段はCircleCIを利用しています
- 1.テスト実行
- 2.テスト成功
- 3.assets precompile を実行
- 4.compileファイルをs3にupload
- 5.デプロイ
machine: environments: timezone: Japan ruby: version: 2.2.3 services: - redis deployment: production: branch: master commands: - ./deploy/circleci/upload_assets.sh - ./deploy/circleci/deployment.sh
#!/bin/sh EXPIRE=`ruby -e "puts (Time.now + (60*60*24*30)).strftime('%Y-%m-%d')"` bundle exec rake assets:precompile RAILS_ENV=production mv ./public/assets/.sprockets-manifest-* ./public/assets/.sprockets-manifest-8jednoecyllbeucnvekdwhbqlkjwhhdq.json aws s3 sync ./public/assets s3://assets.service-domain.com/assets --region ap-northeast-1 --expires $EXPIRE
shellファイルの先頭に #!/bin/sh
(シバン))を記述することはマナー (一応記述がなくても動く)
EXPIRE
でS3内のファイル有効期限を指定 (今回は30日間にセット)
mv コマンドで生成したmanifestの32文字の乱数部分を同一のものに変更 (今回は決めの値を記述しましたが、32文字であれば何でも大丈夫)
Rails側の設定
Rails側でassetsの配信設定を行います
config/environments/production.rb
config.action_controller.asset_host = ""
デフォルトではコメントアウトになっています、asset_hostに配信のURLを指定します。
config.acrion_controller.asset_host = "https://assets.service-domain.com"
precompile後のファイルはS3に置きますが、manifestファイルはWebサーバーのpublic/assets以下に置かなければうまく参照できず正しく表示されません。 Deployのタスク内でmanifestファイルのみをs3から取ってくる処理を書きます。
execute "aws s3 cp assets manifest" do cwd release_path command "aws s3 cp s3://assets.service-domain.com/assets/.sprockets-manifest-8jednoecyllbeucnvekdwhbqlkjwhhdq.json ./public/assets/" environment "RAILS_ENV" => rails_env end
今回はaws s3 cp
コマンドで設置方法
sprocketsのmanifestファイル
- そもそもmanifestファイルってなんのために存在するの?
- manifestファイルではコンパイルされたassetsファイルのルートを指示する
.sprockets-manifest-8jednoecyllbeucnvekdwhbqlkjwhhdq.json
S3でクロスオリジンの設定
RailsでFontawsomeなどを利用している場合、上記の手順でDeployし表示できるが、Fontawsomeのアイコンが豆腐になってしまう問題が発生する。 この問題はクロスオリジンの設定をすることで解決できる。
うまく設定できるまで幾つか地雷を踏みましたがうまく設定できました。