nginxで静的コンテンツをキャッシュ配信する方法

インフラ

画像をはじめとした静的コンテンツをキャッシュし、Webサーバから配信することでアプリケーションのパフォーマンス向上が期待できます。

今回はnginxで静的コンテンツをキャッシュ配信する方法について紹介します。

nginxによる静的コンテンツ配信の概要

locationを利用して『静的コンテンツへのリクエストはnginxで処理、それ以外はアプリケーションで処理』という設定をすることでnginxから静的コンテンツを配信できます。
locationとはリクエストごとに処理を分ける際に利用するnginxのディレクティブです。

locationは以下のパターンを利用してリクエストを振り分けます。1

パターン 意味
なし 前方一致
^~ 前方一致。一致したら、正規表現の条件を評価しない。
= 完全一致。パスが等しい場合。
~ 正規表現(大文字・小文字を区別する)
~* 正規表現(大文字・小文字を区別しない)

静的コンテンツをキャッシュし、nginxから配信する方法

静的コンテンツをnginxで配信するための設定ファイルの紹介をします。
今回は以下のようなケースを想定します。

今回想定するケース
  • 静的コンテンツは『/app/public/』ディレクトリに保存されている
  • 『/app/public/images』配下の画像をnginxから配信する
  • キャッシュ時間は1日とする

前方一致でパスを指定する方法

location /app/public/images//app/public/images/配下へのファイルアクセスがnginxで処理されます。
つまり、画像へのアクセスはアプリケーションではなくnginxで処理されます。

キャッシュはexpires [キャッシュ時間]で設定できます。

nginx.conf

upstream web {
  # UNIXドメインソケット通信の設定
  server unix:///srv/app/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  listen 80;
  server_name  example.com;

  # /app/public/images/ 配下へのアクセス
  location /app/public/images/ {
    expires 24h; # 24時間キャッシュする
  }

  # 上記の条件にマッチしなかったアクセス
  location / {
    # 『web』upstreamへプロキシさせる
    # つまり、アプリケーションで処理される
    proxy_pass http://web;
  }
}

rootディレクティブを利用すると以下のようにかけます。

nginx.conf

server {
  listen 80;
  server_name  example.com;

  # 静的ファイルのパス
  root /app/public;

  # /app/public/images/ 配下へのアクセス
  location /images/ {
    expires 24h;
  }

  # 上記の条件にマッチしなかったアクセス
  location / {
    (略)
  }
}

正規表現でパスを指定する場合

location ~ ^/images//images/配下へのファイルアクセスがnginxで処理されます。
正規表現を利用した設定ファイルは以下の通りです。

nginx.conf

server {
  listen 80;
  server_name  example.com;

  # 静的ファイルのパス
  root /app/public;

  # /app/public/images/ 配下へのアクセス
  location ~ ^/images/ {
    expires 24h;
  }

  # 上記の条件にマッチしなかったアクセス
  location / {
    (略)
  }
}

正規表現を利用することでlocationの一致条件を簡単に拡張できます。

たとえば/images/だけでなく、/hoge/もキャッシュ対象のディレクトリする場合は、location ~ ^/(images|hoge)/という正規表現になります。

正規表現でファイルの拡張子を指定する方法

正規表現でファイルの拡張子を指定することで、ディレクトリ単位ではなくファイル単位で処理を分けられます。

たとえばimagesディレクトリにある.jpeg.JPEG.jpg``.JPG.pngのファイルをキャッシュする場合は以下のようになります。

nginx.conf

server {
  listen 80;
  server_name  example.com;

  # 静的ファイルのパス
  root /app/public;

  # マッチする例
  # /app/public/images/hoge.jpeg
  location ~* ^/images/(.*\.(jpe?g|png))$ {
    # ^ : 先頭マッチ
    # $ : 末尾マッチ
    # .* : 任意の文字が0回以上出現
    # \ : 直後の文字をエスケープ
    # ? : 直前の文字が0回以上出現
    expires 24h;
  }

  # 上記の条件にマッチしなかったアクセス
  location / {
    (略)
  }
}

もし/app/publicディレクトリにある.jpeg.JPEG.jpg``.JPG.pngのファイルをキャッシュする場合は以下のようになります。

nginx.conf

server {
  listen 80;
  server_name  example.com;

  # 静的ファイルのパス
  root /app/public;

  # マッチする例
  # /app/public/hoge.png
  # /app/public/images/hoge.png
  location ~* .*\.(jpe?g|png)$ {
    expires 24h;
  }

  # 上記の条件にマッチしなかったアクセス
  location / {
    (略)
  }
}

参考: Railsアプリケーション上のnginxから画像をキャッシュ配信する

Railsアプリケーション上のnginxから画像をキャッシュ配信する手順について紹介します。
今回はチームで共有するための『Rails 6 x MySQL 8』Docker環境構築手順で紹介したDocker Compose環境を利用します。

サンプルアプリケーションの作成

画像を表示する画面のルーティングを作成します。

routes.rb

Rails.application.routes.draw do
+ root to: 'home#index'
end

コントローラとビューの作成をします。

$ rails g controller home index

キャッシュ配信するサンプルとして今回はpublic/images/group_young_world.pngという画像を用意します。

$ ls public/images/group_young_world.png

group_young_world.png

画面を作成します。

views/home/index.html.erb

<%= image_tag '/images/group_young_world.png', width: '500' %>

localhost:3000にアクセスして画像が表示されればOKです。

アプリケーションサーバにnginxをインストール

Railsが実行されているアプリケーションサーバにnginxをインストールします。

### ローカルで実行
$ /path/to/project
$ docker-compose exec web /bin/bash

### webコンテナ上で実行
$ apt update && apt install -y nginx vim

nginxの設定ファイルを追加する

nginxの設定ファイル(/etc/nginx/nginx.conf)のinclude /etc/nginx/conf.d/*.conf;という記述からわかる通り、nginxは/etc/nginx/conf.d/配下の*.confファイルを設定として読み込みます。
そこで今回は/etc/nginx/conf.d/default.confという名前の設定ファイルを作成します。

$ mkdir -p /etc/nginx/conf.d
$ vim /etc/nginx/conf.d/default.conf

/etc/nginx/conf.d/default.conf

server {
  listen 80;
  server_name  localhost;

  # 静的ファイルのパス
  root /rails6_mysql8/public;

  location /images/ {
    expires 300;
  }

  location / {
    proxy_set_header Host localhost;
    proxy_pass http://web:3000;
  }
}

設定ファイル作成後、configtestコマンドで文法誤りがないかチェックします。

### nginx.confの記述が正しいかチェック
$ /etc/init.d/nginx configtest

[ ok ] Testing nginx configuration:.

画面のキャッシュが有効になっているか確認する

設定ファイル作成後、nginxの起動をします。

$ service nginx start

localhostにアクセスすると画像が表示されます。
画像のレスポンスヘッダを確認すると先ほど設定したキャッシュ時間(300秒)が反映されていることがわかります。

まとめ

今回のまとめ
  • nginxでコンテンツを配信する場合はlocationディレクティブを利用する
  • expiresで静的ファイルをキャッシュ配信できる

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!

参考