- はじめに
- nginx のプロセス
- docker で nginx を導入する
- nginx の構成
- nginx コマンド
- nginx の基本設定
- location ディレクティブのマッチング
- アクセス制限を行う
はじめに
Docker による nginx の導入と、nginx の基本設定についての説明です。
nginx のプロセス
nginx は master プロセスでソケットのリスンを行います。
ソケットで待ち受けた接続は、worker プロセスに引き渡され、 accept と送受信といったネットワークI/O処理を行います。
master プロセスは root ユーザで起動し、worker プロセスは一般ユーザ(nginx や www など)で起動します。
worker プロセスでは、epoll や kqueue などを利用した I/O の多重化により、1つのプロセスで複数のクライアントとの会話を処理することができます。これにより大量のクライアントとの接続を少ないリソースで捌くことができます。
docker で nginx を導入する
作業フォルダを作成してdocker-compose.yml
を作成します。
$ mkdir nginx $ cd nginx $ touch docker-compose.yml
docker-compose.yml
を以下のように作成します。
version: '3.8' services: nginx: container_name: "nginx" image: nginx:1.19 ports: - "80:80" volumes: - ./html:/usr/share/nginx/html
それでは nginx を起動してみましょう。
$ docker-compose up -d
同フォルダの html
に HTML ファイルを用意します。
$ cd html $ cat <<EOF > index.html <!DOCTYPE html> <html><body><h1>Hello nginx</h1></body></html> EOF
http://localhost/index.html
にアクセスすれば作成した HTML が表示されます。
nginx の構成
コンテナにログインしてnginxの構成を見てみましょう。
$ docker-compose exec nginx bash
主なディレクトリ構成は以下のようになっています。
ファイル/ディレクトリ | 説明 |
---|---|
/etc/nginx/nginx.conf | 起点となる設定ファイルで、他の設定ファイルはここから読み込まれる |
/etc/nginx/conf.d/default.conf | webサーバの設定ファイル |
/etc/nginx/mime.types | MIME のマッピングファイル |
/usr/share/nginx/html/ | webサーバのドキュメントルート |
/etc/logrotate.d/nginx | ログローテーションの設定ファイル |
/var/log/nginx/ | ログ・ファイルの出力先ディレクトリ |
/var/cache/nginx/ | キャッシュファイルが格納先ディレクトリ |
nginx コマンド
nginx コマンドは以下のようなオプションがあります。
$ nginx -h nginx version: nginx/1.17.4 Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives] Options: -?,-h : this help -v : show version and exit -V : show version and configure options then exit -t : test configuration and exit -T : test configuration, dump it and exit -q : suppress non-error messages during configuration testing -s signal : send signal to a master process: stop, quit, reopen, reload -p prefix : set prefix path (default: /etc/nginx/) -c filename : set configuration file (default: /etc/nginx/nginx.conf) -g directives : set global directives out of configuration file
よく使うのは以下になります。
nginx -t
で設定ファイルをテストしてエラー内容を表示nginx -s reload
設定ファイルの再読み込みを行うnginx -s stop
実行中の nginx デーモンを停止nginx -s quit
処理中のリクエスト完了を待って nginx デーモンを停止
nginx の基本設定
/etc/nginx/nginx.conf
が基本設定となります。
中身を見てみましょう。
$ cat nginx.conf
nginx.conf
は以下のような設定になっています。
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
worker プロセスのユーザ名と worker プロセスの数が以下のように定義されています。
これら設定のことをディレクティブと呼びます。
user nginx; worker_processes 1;
プロセス数はデフォルトで1となっていますが worker_processes auto;
とすることで、CPUコア数と同数のプロセスを選択することができます。
次にあるのはエラーログの出力先とログレベルの設定です。
error_log /var/log/nginx/error.log warn;
ログレベルには debug, info, notice, warn, error, crit, alert, emerg が設定可能です。
続いてプロセスIDの記載先となるPIDファイルの格納先の指定です。
pid /var/run/nginx.pid;
プロセスIDが記載されます。
次にあるのは events
コンテキストです。
events { worker_connections 1024; }
nginx の設定ファイルでは、<モジュール名> { }
という形でそれぞれのモジュールに対する設定を行います。
指定したモジュールのスコープは { }
で囲まれた範囲となり、これをコンテキストと呼びます。
先に見た設定値はルートに配備されており、これを main コンテキストと呼びます。
events
コンテキストでは、 worker_connections
とにて、イベントループを行う worker プロセスで同時に受付可能な接続数を定義しています。
次にあるのが http
コンテキストであり、web サーバの設定をここに記載します。
http
コンテキストの先頭にあるのは、MIMEタイプのマッピングファイルのインクルードです。
include /etc/nginx/mime.types; default_type application/octet-stream;
default_type
では、マッピング定義が存在しない場合の content-type を定義しています。
次にあるのはアクセスログのフォーマット定義です。
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
main という名前でアクセスログに出力する項目を定義しています。変数についてはAlphabetical index of variables が参考になります。
続く行で main として定義したログフォーマットを使い、アクセスログに出力場所を定義しています。
access_log /var/log/nginx/access.log main;
次にあるのが以下のような http 通信に関する設定です。
sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on;
それぞれ以下の設定になります。
sendfile
クライアントへのレスポンス送信に sendfileシステムコール を利用するかどうか(I/Oパフォーマンスが向上するが一部の環境で不具合が発生する場合がある)tcp_nopush
on とすることで(sendfile が on の場合)レスポンスヘッダどレスポンスボディをまとめて送信するようになりパケットの利用が効率的になるkeepalive_timeout
サーバのkeepaliveタイムアウト秒数を設定。タイムアウト内の連続したリクエストにコネクションが使い回されるようになるgzip
コンテンツをgzip 圧縮して通信量を減らす。デフォルトで圧縮対象はtext/html
となるため、他のコンテンツを対象にするにはgzip_types text/css text/javascript;
のように指定する
http
コンテキストの最後では別の設定ファイルを読み込んでいます。
include /etc/nginx/conf.d/*.conf;
対象ディレクトリには default.conf
があり、以下のように定義されています。
server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
http
コンテキストの中の server
コンテキストになります。
server
コンテキストは複数を並列に書くことで、バーチャルホストを複数定義できます。通常は xxx.conf
のような定義を /etc/nginx/conf.d/
配下に配備することになります。
設定内容を見ていきます。最初はこのバーチャルホストの待ち受けポートとバーチャルホストのサーバ名を定義しています。
listen 80; server_name localhost;
server_name
はスペース区入りで複数書くこともできますし、正規表現やワイルドカードを使って書くこともできます。HTTPリクエストの Host
ヘッダから、該当するバーチャルホストが選択されます。
Host
ヘッダ名にマッチするものが無かった場合のデフォルトを指定する場合には以下のように指定しておくことで、対象のバーチャルホストが選択されます。
listen 80 default_server;
次にあるのが location
ディレクティブで、HTTPリクエストパスに応じたコンテキストを定義します。
location / { root /usr/share/nginx/html; index index.html index.htm; }
root
ディレクティブでは対象のパスに対応したドキュメントルートを指定します。
index
ディレクティブでは、ここでの例では localhost/
でアクセス時に利用されるファイルを指定します。
最後にあるのがエラーレスポンス用のページの定義となります。
error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; }
error_page
ディレクティブでは、HTTPレスポンスコードに応じたエラーページを指定しています。この例では /50x.html
ファイルにリダイレクトします。
location
ディレクティブは先の説明と同様で、リダイレクトしたパスに応じたドキュメントルートを指定しています。エラーページは /50x.html
ファイルでカスタマイズすることができます。
default.conf
をローカル側で編集するには docker-compose.yml
を以下のようにしてマウントします。
version: '3.8' services: nginx: container_name: "nginx" image: nginx ports: - "80:80" volumes: - ./default.conf:/etc/nginx/conf.d/default.conf:ro - ./html:/usr/share/nginx/html
default.conf
のマウントは読み込み専用のアクセス(ro
) として指定しています(読み書きの場合は rw
を指定できます)。
location ディレクティブのマッチング
location ディレクティブは引数のパスに応じたコンテキストを作成します。
パス名はいくつかの書式が用意されています。
location <pass> { }
パス名の前方一致。/
とすると全てのパスにマッチするlocation = <pass> { }
パス名の完全一致location ~ <pattern> { }
正規表現でパス名にマッチするパターンを指定するlocation ^~ <pattern>
正規表現より優先度の高い前方一致location @<name>
パス名に直接マッチしない名前付きロケーション
名前付きロケーションは以下のように利用します。
location / { try_file $uri @fallback } location @fallback { ... }
try_file
ディレクティブは指定されたレスポンスが見つかるかを試行し、レスポンス用のファイルが見つからなければ名前付きロケーションとなっている @fallback
を試行します。
location ディレクティブの優先順位は 完全一致 > 最長の前方一致で ^~
が付いたもの > 正規表現による最初の一致 > 最長の前方一致 の順番になります。
アクセス制限を行う
IPアドレスによりアクセス制限を行うには location
ディレクティブ内に、allow
と deny
にてIPアドレスを指定することで可能です。
location /private { allow 192.168.1.0/24; deny all; }
アクセス制限は、上から見ていき最初に一致した設定内容で制御が行われます。
Basic 認証を行うには、auth_basic_user_file
ディレクティブを指定します。
location /private { auth_basic "Basic Auth"; auth_basic_user_file /etc/nginx/htpasswd; }
auth_basic
には何らかの文字列を設定すれば Basic 認証が on となります。ブラウザによってはこの文字列を認証画面に表示することがあります。off とする場合は off
と記載すれば良いです。
パスワードファイルは htpasswd
コマンドで作成します。
$ htpasswd -b -c htpasswd user pass $ cat htpasswd user:$apr1$aaM0XmBZ$Ibx...
とすることで htpasswd
ファイルが作成されます。-c
でパスワードファイルの新規作成、-b
で対話形式でなく、コマンドラインからのオプションでユーザ名とパスワードを指定する意味となります。
docker-compose.yml
で以下のようにマウントすればBasic認証が使えます。
volumes: - ./htpasswd:/etc/nginx/htpasswd:ro