Nginxロケーションブロック完全解説:Webトラフィックのルーティング

Nginxのロケーションブロックは、効率的なWebトラフィックルーティングの基盤です。この包括的なガイドでは、5つの異なるマッチング修飾子(プレフィックス、完全一致、最長プレフィックス、正規表現)と、Nginxが従う厳格な処理順序を解説します。実際の設定例を用いて、静的アセットの正確なルーティング、API呼び出しのプロキシ、セキュリティルールの実装方法を学びます。ロケーションブロックをマスターすることは、正確なトラフィック制御、高速なサーバーパフォーマンス、堅牢な設定管理の鍵です。

Nginxロケーションブロック完全解説:Webトラフィックのルーティング

Nginxのロケーションブロックは、リクエストが適切なserverブロックに到達した後の処理を決定します。これにより、/static/app.cssをディスクから提供したり、/api/usersをアプリケーションにプロキシしたり、/.git/configへのアクセスを機密情報漏洩前に拒否したりすることが可能になります。

ロケーションブロックに関するほとんどのミスは構文エラーではなく、優先順位の誤りです。正規表現がプレフィックスブロックで処理すべきリクエストを横取りしたり、rootパスが想定以上にURIを追加したり、proxy_passの末尾スラッシュの有無でアップストリームURIの書き換え方が変わったりします。以下の例では、これらの実際の障害点に焦点を当てています。

ロケーションブロックの役割と構造

locationブロックは、NginxがリクエストURI(Uniform Resource Identifier)に基づいてどのように応答するかを定義します。これらのブロックは常にserverブロック内にネストされます。

クライアントがリクエスト(例:GET /images/logo.png)を行うと、Nginxはリッスンしているserverブロック内のすべての定義済みロケーションブロックに対してリクエストURIをチェックし、ファイルの提供、クライアントのリダイレクト、アプリケーションサーバーへのプロキシなど、適切な処理を決定します。

基本構文

構文では、修飾子(またはその欠如)の後にパターン(URI)が必要です。

location [修飾子] [パターン] {
    # 設定ディレクティブ(例:root, index, proxy_pass)
}

ロケーションマッチタイプの理解(修飾子)

Nginxは少数のロケーションマッチスタイルを提供します。選択はルーティングの精度と、ハンドラを選択する前にNginxが行う処理量の両方に影響します。

1. プレフィックス一致(修飾子なし)

これはデフォルトのマッチタイプです。NginxはリクエストURIに一致する最長の開始文字列を検索します。

修飾子 動作 最適なユースケース
(なし) location /blog/ /blog/で始まるURIに一致(例:/blog/post/1)。 汎用的に使用し、サイトの大きなセクションを定義。

例:

location /docs/ {
    root /var/www/html/public;
    # URIが/docs/manual.pdfの場合、Nginxは/var/www/html/public/docs/manual.pdfを探します
}

2. 完全一致(=

この修飾子はURIとパターンの完全一致を強制します。一致した場合、Nginxは他のロケーションの検索を即座に停止します。これは最速のマッチタイプです。

修飾子 動作 最適なユースケース
= location = /favicon.ico URI /favicon.icoにのみ完全一致。 特定の頻繁にリクエストされるファイルやデフォルトページの処理。

3. 最長プレフィックス、非正規表現(^~

これは特殊なプレフィックス一致です。Nginxが^~を使用して最長プレフィックス一致を見つけた場合、正規表現(regex)ロケーションブロックのチェックを即座に停止し、事実上それらを上書きします。

修飾子 動作 最適なユースケース
^~ location ^~ /assets/ /assets/で始まるURIに一致し、低速な正規表現マッチのチェックを防止。 静的アセットを迅速に提供し、アセットディレクトリが予測可能に処理されることを保証。

4. 大文字小文字を区別する正規表現(~

これはPerl互換正規表現(PCRE)を使用してマッチングを行います。強力ですが、プレフィックス一致よりも低速です。最初に一致した正規表現ブロックが優先されます。

修飾子 動作 最適なユースケース
~ location ~ \.php$ .phpで終わる任意のURIに一致。 特定のファイルタイプの処理(例:PHPスクリプトをPHP-FPMに渡す)。

5. 大文字小文字を区別しない正規表現(~*

~と同一ですが、マッチング時にURIの大文字小文字を無視します。

修飾子 動作 最適なユースケース
~* `location ~* .(jpg gif png)$`

重要なロケーション処理順序

Nginxがロケーションブロックを処理する順序を理解することは、予期しない動作を避けるために不可欠です。Nginxは設定ファイルを単純に上から下に読むわけではありません。厳格な階層を使用します。

  1. 完全一致(=): Nginxは最初にすべての完全一致ブロックをチェックします。一致が見つかった場合、処理は即座に停止し、そのブロックがリクエストを処理します。
  2. 最長プレフィックス候補: Nginxは、通常のプレフィックスロケーションと^~ロケーションを含む、最長一致するプレフィックスロケーションを見つけます。
  3. ^~の正規表現スキップ: その最適なプレフィックス一致が^~を使用している場合、Nginxはそれを使用し、正規表現チェックをスキップします。
  4. 正規表現(~および~*): 最適なプレフィックスが^~でなかった場合、Nginxは設定ファイルに出現する順序で正規表現ロケーションをチェックします。最初に一致した正規表現ブロックが優先されます。
  5. 最長標準プレフィックス一致: 正規表現の一致がなかった場合、Nginxは既に見つけた最長プレフィックス候補を使用します。多くの設定では、location /が最終的なフォールバックとなります。

これが^~ /static/が一般的である理由です。^~がない場合、後続の正規表現location ~* \.(css|js)$/static/app.cssに対して優先される可能性があります。それが問題ない場合もありますが、/static/ディレクトリ全体に期待したキャッシュヘッダー、ルートパス、アクセスルールをバイパスしてしまうことがあります。

実践的な設定シナリオ

1. パフォーマンスのための静的アセットの優先

Nginxが静的ファイルを直接迅速に提供し、低速な正規表現チェックやアプリケーションサーバーによる不要な処理を防ぐために、^~修飾子を使用します。

server {
    listen 80;
    server_name myapp.com;

    # 1. メインページの完全一致(最高優先度)
    location = / {
        proxy_pass http://backend_app_server;
    }

    # 2. 静的アセットの高速処理、正規表現チェックをバイパス
    location ^~ /static/ {
        root /var/www/site;
        expires 30d;
    }

    # 3. 一般的なメディアファイルの正規表現
    location ~* \.(gif|ico|css|js)$ {
        root /var/www/site;
        expires 7d;
    }

    # 4. その他すべての動的リクエストのフォールバック
    location / {
        proxy_pass http://backend_app_server;
    }
}

2. APIトラフィックのルーティングとプロキシ

Nginxをリバースプロキシとして使用する場合、ロケーションブロックはトラフィックを適切なアップストリームアプリケーションサーバーに転送します。

location /api/v1/ {
    # クライアント接続設定をNginxが尊重するようにする
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    # /api/v1/で始まるすべてのトラフィックをバックエンドサービスにルーティング
    proxy_pass http://api_backend_service/v1/;

    # proxy_passにURIがある場合、Nginxは一致したプレフィックスを置き換えます。
    # /api/v1/usersはアップストリームで/v1/usersになります。
}

末尾スラッシュの動作はテストする価値があります。以下の2つの例は異なります。

location /api/ {
    proxy_pass http://api_backend;
}

location /api/ {
    proxy_pass http://api_backend/;
}

最初の形式は、/api/...を含む元のURIをそのままアップストリームに渡します。2番目の形式は、一致した/api/プレフィックスを/に置き換えます。小さな設定編集後にアップストリームが突然404を返し始めた場合、アプリを責める前にこれを確認してください。

3. 機密ディレクトリの保護

ロケーションブロックを使用して、設定ファイルや.gitのような隠しディレクトリなど、機密性の高い内部ディレクトリへの外部アクセスを拒否できます。

# ドットで始まるファイル(隠しファイル)へのアクセスを拒否
location ~ /\.(ht|svn|git) {
    deny all;
    return 404; # 存在を隠すために403ではなく404を返す
}

# 特定の設定ディレクトリへのアクセスを拒否
location /app/config/ {
    deny all;
}

隠しファイルについては、多くのチームがより広範な拒否ルールを使用します。

location ~ /\.(?!well-known/) {
    deny all;
    return 404;
}

例外により、ACME HTTP-01証明書チャレンジなどのために/.well-known/を利用可能にしつつ、ほとんどのドットファイルをブロックします。サイトが他の正当なドットプレフィックスパスを提供する場合は、これを注意深くテストしてください。

セキュリティ警告:aliasrootの使い分け

ロケーションブロック内でファイルパスを設定する際は、rootaliasの違いに注意してください。

  • root 定義されたパスに完全なリクエストURIを追加します。(例:location /images/ + root /data//data/images/filename.jpg になります)
  • alias URIの一致した部分を定義されたパスで置き換えます。これは、ロケーションブロックが正規表現を使用する場合や、ファイルを提供する前にパスの一部を削除する必要がある場合に必要です。(例:location /static/ + alias /opt/app/files//opt/app/files/filename.jpg になります)

4. 末尾スラッシュとリダイレクトの処理

ディレクトリが常に末尾スラッシュ(/)で終わるようにするなど、一貫したURL構造を強制することが望ましい場合があります。

# ディレクトリパスに末尾スラッシュがない場合に強制
location ~* /[a-z0-9\-_]+$ {
    # URIがファイルに一致する場合、Nginxはそれを提供しようとします。そうでない場合はディレクトリとして扱います。
    # リクエストされたURIがディスク上のディレクトリにマップされるか確認:
    if (-d $request_filename) {
        return 301 $uri/;
    }
}

ロケーションルーティングのデバッグに役立つ方法

リクエストが間違った場所に到達した場合、問題を1つのURLと1つのserverブロックに絞り込みます。nginx -Tを実行して、インクルードされたファイルを含む完全なレンダリング設定を表示し、そのURIに一致する可能性のあるすべてのロケーションを検索します。ファイル内の順序が重要であるため、正規表現ブロックに特に注意してください。

静的ファイルの場合は、rootまたはaliasからNginxが構築するファイルシステムパスを確認します。プロキシリクエストの場合は、proxy_passがアップストリーム名の後にURI部分を含むかどうかを確認します。その後、nginx -tが成功した場合にのみリロードします。

ロケーションブロックは、優先順位ルールを内部化すれば予測可能ですが、コピー&ペーストで設定が増えると容赦がありません。小さなホットパスには完全一致を、正規表現処理をバイパスすべきディレクトリには^~を、パターンマッチングが本当に必要な場合にのみ正規表現を、そして明確なフォールバックとしてプレーンなlocation /を使用してください。