Panda Noir

JavaScript の限界を究めるブログでした。最近は幅広めに書いてます。

Nginxでlocationの書き方がわからない時に読む記事

「Nginxのlocationの書き方がわからない!」そう思ったことはありませんか?

  • ネストするとおかしくなる
  • 同じ階層にあるうち一つしか適用されない

など 、locationディレクティブは直感的でない、クセがある動作をします。

今回、Nginx実践入門とNginxドキュメントを読んで理解が深まったので、自分なりにベストプラクティスをまとめてみました。

locationの基礎事項

まずlocationの基礎知識ですが、locationは並列して書かれていた場合、どれか一つのみ適用されます。どれが適用されるかは演算子によります。

「=、^~、~、~*、なし」の順に適用されます。

=完全一致
^~前方一致
~case-sensitive*1な正規表現
~case-insensitive*2な正規表現
なし前方一致

^~と「演算子なし」は正規表現に対する優先順位が異なります。

ネストはしてもいい

locationのネストはしてはいけないという記事がありますが、locationはネストしていいですドキュメントにキッパリ書いてあります。バリバリ使いましょう。

ネストによる引き継ぎについて

ネストさせてもいい、と書きましたが、これには注意点があります。それは、引き継ぎがうまく出来ないケースがあることです。

location /hoge {
  # configure A
  location ~ ^/hoge/.*\.php {
    # configure B
  }
  location ~ .* {
    # configure C
  }
}

このときconfigure Aは適用されないことがあります。引き継ぎされることはあるのですが、されないディレクティブもあるようです。これはドキュメントを読んでも明示されていなかったので、どういう仕様かは分かりません。しかし、configure Aは何も書かないのが無難でしょう。

個人的ベストプラクティス

さて、以下は僕的ベストプラクティスです。

さきほど優先順位の話をしましたが、優先順位なんて忘れてください。全く必要ありません。なぜかというと、優先順位を活用しようとするとファイルを分割したときに困るからです。同じ層を複数ファイルに分けたとき、全てのファイルの演算子を覚えて、どれが適用されるのか調べるのはとても大変です。

ならどうすればいいのでしょうか?正解は「同じ層は同じ演算子のみ」にすればいいのです。そうすればどれが適用されるのか、演算子で迷うことがなくなります。

どういう書き方にするかというと、まず第一層は「演算子なし」のlocationのみで書きます。そして第二層には正規表現を使って書いていきます。

実例

まず、ディレクトリ名で分けます。

そしてネストした中に「完全一致」「正規表現」「その他のケース」を書きます。

location /hoge {
  #ここには書かない
  location = /hoge/fuga {
    # 完全一致のケース
    #configure B
  }
  location ~ ^/hoge/.*\.php$ {
    # 正規表現のケース
    # configure C
  }
  location /hoge {
    # 上のケースに当てはまらなかった場合
    # configure D
  }
}
location /fuga {
  #ここには書かない
  location ~ ^/fuga/.*\.php$ {
  }
  location /fuga {
  }
}
location /{
  #ここには書かない
  location ~ \.php$ {
    # configure B
  }
  location / {
    # configure C
  }
}

このように書くことで、ディレクトリごとに設定がわかれて、ファイルを分割しやすくなります。また、優先度はすべて同じになるので、他の設定との競合を防ぎやすくなります。

ただし、この方法はネストを使っているのでパフォーマンスは落ちてしまいます。大規模サービスを作ると影響が出てくるかもしれません。

*1:大文字と小文字を区別する

*2:大文字と小文字を区別しない