【Azure】App Service「だけ」でキャッシュのレスポンスヘッダを設定する(NGINX編)Tech TIPS

Azure App Service on LinuxでWebサーバ/アプリを運用していて、コンテンツのキャッシュ期間などを設定したいと思ったことはないだろうか? Front Doorなど有料のクラウドサービスを追加することなく、App Service単体でキャッシュを制御するレスポンスヘッダを追加する方法を紹介する。

» 2025年03月26日 05時00分 公開
[島田広道デジタルアドバンテージ]
「Tech TIPS」のインデックス

連載目次

Azure App Serviceでキャッシュ用ヘッダ追加

対象:Azure App Service on Linux

 Azureの「App Service」でWebサイト/アプリを構築した場合、デフォルトではWebブラウザやキャッシュサーバ(リバースプロキシやロードバランサー)のキャッシュ機能を制御するためのレスポンスヘッダが付加されない。

 しかし、クライアントでの性能を高めつつ、Webサーバ側の負荷を軽減するには、可能な限りキャッシュ期間を設定したいところだ。

 Azureの場合、「Front Door」というリバースプロキシ/キャッシュサーバのサービスを使うと、キャッシュ制御のレスポンスヘッダを付加できる。しかし、それにはApp Serviceとは別に追加コストが必要になってしまう。

 そこで本Tech TIPSでは、App Service内蔵のNGINXの設定を変更することで、コンテンツのキャッシュ期間などを設定する方法を紹介しよう。App Serviceの機能なので追加コストは不要だ。また、PHPなどでは面倒な画像などの静的ファイルに対する設定もNGINXなら可能だ。

 App Service内蔵のNGINXの設定変更については、「【Azure】App ServiceのWebサーバ『NGINX』をカスタマイズする方法」を前提としているので、以下を読み進める前に参照していただきたい。また、「【Azure】App Service on LinuxでディレクトリごとにクライアントIP制限を実装する方法と注意点」も参考になるだろう。

【基本】NGINXの「expires」ディレクティブでキャッシュ期限を設定する

 NGINXでコンテンツのキャッシュ期限を設定するには、「expires」ディレクティブを用いる。

expires <キャッシュ期間(秒)>s;
expires <キャッシュ期間(分)>m;
expires <キャッシュ期間(時)>h;
expires <キャッシュ期間(日)>d;
expires <キャッシュ期間(週)>w;
expires <キャッシュ期間(年)>y;

【NGINX】expiresディレクティブでキャッシュ期間を設定する際の基本的な構文
NGINXのレファレンス: expires

 App Serviceの場合、これを[nginx/sites-available/default]ファイルの「server」または「location」コンテキスト内に記述する。

 例えば、キャッシュ期限をHTTPレスポンス生成の2週間後とするには、以下のように記述すればよい。

expires 2w;

【NGINX】コンテンツに2週間のキャッシュ期間を設定する

 するとレスポンスには、以下のヘッダが追加される。

Cache-Control: max-age=1209600 ← 1209600秒=2週間のキャッシュ期間
Date: Mon, 24 Mar 2025 01:58:24 GMT ← レスポンス生成時刻(デフォルトで出力)
Expires: Mon, 07 Apr 2025 01:58:24 GMT ← キャッシュ期限はレスポンス生成より2週間後

【HTTPレスポンス】上記のNGINX設定で出力されるキャッシュ関連ヘッダ

 「Cache-Control」「Expires」は、ともにキャッシュを制御するためのレスポンスヘッダである。執筆時点で主に使われているのはCache-Controlヘッダの方で、これが指定されていると通常、Expiresヘッダは無視される。Cache-Controlヘッダに対応していない古いWebブラウザやキャッシュサーバでは、Expiresヘッダがキャッシュ制御に用いられる。

常に最新のコンテンツを利用させる(実質的にキャッシュを無効化する)には

 コンテンツによっては、常にオリジンサーバ(コンテンツを生成するサーバ。App Serviceでは内蔵のNGINXによるWebサーバ)から最新のコンテンツを提供したい、ということもよくある。その場合は、expiresディレクティブに「epoch」というパラメーターを指定する。

expires epoch;

【NGINX】常に最新のコンテンツを利用させる(実質的にキャッシュを無効化する)

 するとCache-Control/Expiresレスポンスヘッダは以下のように出力される。

Cache-Control: no-cache ← 最新のコンテンツを利用させる
Expires: Thu, 01 Jan 1970 00:00:01 GMT ← 過去の日時=キャッシュ内のコンテンツを再利用させない

【HTTPレスポンス】上記のNGINX設定で出力されるキャッシュ関連ヘッダ

 この場合、Webブラウザや経路途中のキャッシュサーバ(リバースプロキシやロードバランサーなど)は、キャッシュに対象コンテンツが保存されていた場合、それが最新かどうかをオリジンサーバに問い合わせて検証し、最新ならそれを再利用する。逆に古かったらオリジンサーバから取得し直す。つまり、キャッシュにある古いコンテンツは用いられず、常に最新版が利用されることになる。

 少し注意が必要なのは、コンテンツをキャッシュに保存すること自体は禁止していない点だ。保存を禁止するには、Cache-Controlヘッダに「no-store」という値を指定する必要がある(詳細はすぐ後で説明)。

Webブラウザにもキャッシュサーバにもキャッシュに保存させないようにするには

 前述のように「expires epoch;」と指定しただけだと、Webブラウザやキャッシュサーバにコンテンツの保存を禁止させることはできない。

 キャッシュへの保存も禁止したい場合は、以下のようにexpiresディレクティブと「add_header」ディレクティブを併用する。

expires epoch;
add_header Cache-Control "no-store";

【NGINX】Webブラウザにもキャッシュサーバにもキャッシュに保存させないようにする
NGINXのレファレンス: add_header

 するとCache-Control/Expiresヘッダは以下のように出力される。

Cache-Control: no-cache ← 無視される。「no-store」も指定されているため
Cache-Control: no-store ← コンテンツをキャッシュに保存することを禁止
Expires: Thu, 01 Jan 1970 00:00:01 GMT ← 過去の日時=キャッシュ内のコンテンツを再利用させない

【HTTPレスポンス】上記のNGINX設定で出力されるキャッシュ関連ヘッダ

 Cache-Controlヘッダが複数指定されていた場合、それぞれの値を単一のCache-Controlヘッダにコンマ区切りで記述したのと同じに見なされる。そのため、上記の場合は「no-cache」「no-store」の両方を指定したことになる。ただし「no-cache」は「no-store」に含まれるため、「no-store」のみ指定したのと同じ、つまりキャッシュ保存禁止になる。

キャッシュサーバでのキャッシュ保存を禁止するには

 認証を伴うサイトで、ユーザーごとに保護すべき(漏えいから守るべき)コンテンツについては、経路途中のキャッシュサーバがキャッシュに保存するのを禁止して、不特定多数のユーザー間で共有されないようにする必要がある。それには、Cache-Controlヘッダに「private」という値を付ける。

expires 2w; # 2週間のキャッシュ期間
add_header Cache-Control "private"; # キャッシュサーバでは保存禁止

【NGINX】キャッシュサーバでのキャッシュ保存を禁止する

 NGINXの設定ファイルで上記のように記述すると、対象コンテンツのレスポンスには以下のようなヘッダが付加される。

Cache-Control: max-age=1209600 ← 1209600秒=2週間のキャッシュ期間
Cache-Control: private ← キャッシュサーバでは保存禁止
Date: Mon, 24 Mar 2025 02:04:16 GMT ← レスポンス生成時刻
Expires: Mon, 07 Apr 2025 02:04:16 GMT ← キャッシュ期限は2週間後

【HTTPレスポンス】上記のNGINX設定で出力されるキャッシュ関連ヘッダ

 この場合、Webブラウザのローカルキャッシュでは2週間、コンテンツ(レスポンス)の再利用が可能な一方で、キャッシュサーバでは保存が禁止され、再利用もできない。

BASIC認証下のコンテンツにキャッシュサーバでのキャッシュ保存を許可する

 Tech TIPS「【Azure】App Service on LinuxにBASIC認証を実装する方法と注意点」で説明している方法でBASIC認証を有効にしているコンテンツは通常、キャッシュサーバに保存されない(Webブラウザのローカルキャッシュには保存される)。

 しかし、画像やスタイルシート、JavaScriptなどユーザーごとに内容が変わることがなく、個人情報も含まれないコンテンツについては、キャッシュサーバでキャッシュに保存してもよい。それならばキャッシュにヒットするようにして性能を高めたいところだ。

 そのような場合は、Cache-Controlヘッダに「public」という値を付ける。

expires 2w; # 2週間のキャッシュ期間
add_header Cache-Control "public"; # キャッシュサーバに保存可能

【NGINX】BASIC認証下のコンテンツにキャッシュサーバでのキャッシュ保存を許可する

 NGINXの設定ファイルで上記のように記述すると、対象コンテンツのレスポンスには以下のようなヘッダが付加される。

Cache-Control: max-age=1209600 ← 1209600秒=2週間のキャッシュ期間
Cache-Control: public ← キャッシュサーバで保存可能
Date: Mon, 24 Mar 2025 02:04:16 GMT ← レスポンス生成時刻
Expires: Mon, 07 Apr 2025 02:04:16 GMT ← キャッシュ期限は2週間後

【HTTPレスポンス】上記のNGINX設定で出力されるキャッシュ関連ヘッダ

 この場合、Webブラウザでもキャッシュサーバでも2週間、コンテンツ(レスポンス)の再利用が可能になる。

特定条件下でCache-Control/Expiresヘッダの出力を取り消すには

 デフォルトで何らかのCache-Control/Expiresヘッダを出力しているサイトでは、コンテンツによって、これらのヘッダをNGINX側で付けてほしくない場合もあるだろう。

 そのような時には、対象のlocationコンテキスト内で「expires off;」と記述すればよい。

server {
<前略>
    # 以下のキャッシュ期限の設定は、このserverコンテキスト全体で追加(継承)される
    expires 1w;

    # [/dir1]ディレクトリ以下に限定
    location ~ ^/dir1/ {
        # serverコンテキストで設定されたCache-Control/Expiresヘッダの出力を取り消す
        expires off;
        
        # 必要なら、ここにその他のディレクティブを記述
    }
<後略>
}

【NGINX】特定のディレクトリ以下でCache-Control/Expiresヘッダの出力を取り消す
設定ファイル: /home/custom/etc/nginx/sites-available/default

 上記の場合、NGINXは[/dir1]ディレクトリ以下のコンテンツをリクエストされたとき、Cache-Control/Expiresヘッダを付けないでレスポンスを返す(その他のディレクトリでは付ける)。これにより、例えば[/dir1]以下にあるPHPなどのプログラムコード側で、最適な値を設定したCache-Control/Expiresヘッダを出力する、といったことが可能になる。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

Windows Server Insider 記事ランキング

本日月間

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。