nginxで静的コンテンツを表示する

目的

nginxのDockerコンテナを使って静的コンテンツを表示するための基本的な設定を抑える。
使用するnginxのバージョンは1.13.12。

デフォルトの設定

nginx:1.13-alpine のDockerイメージでは、/etc/nginx/nginx.conf/etc/nginx/conf.d/default.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;
    keepalive_timeout  65;
    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;
    }
}

公開ディレクトリが /usr/share/nginx/html に設定されていて、 /test.html でリクエストすると /usr/share/nginx/html/test.html ファイルが表示されるようになっている。

ディレクティブの解説

ディレクティブとは

設定ファイルのそれぞれの項目はディレクティブと呼ばれ、ディレクティブ名とパラメータはスペースまたはタブ文字で区切り、最後にセミコロンを付ける。
各行の # 以降は行末まで全てコメントとして扱われる。
ディレクティブには ; で終わるシンプルなディレクティブと、{...} でブロックをとるディレクティブがある。

シンプルなディレクティブ

  • パラメータが1つだけ
    worker_processes 1;

  • パラメータが複数 error_page 500 502 503 504 /50x.html;
    各パラメータの間は空白文字で区切る。

  • 複数パラメータを改行で区切って指定可能

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

ブロック付きディレクティブ

ディレクティブには有効範囲(コンテキスト)があり、httpserverディレクティブのブロックで指定されたコンテキストや、どのコンテキストにも所属しないmainコンテキストがある。mainコンテキストで指定された値はブロック内でも有効だが、ブロック内で指定されると値は上書きされる。

root   /usr/share/nginx/html;  # ①
server { # A
    server_name  a.example;
    root   /usr/share/nginx/html/a; # ②
}
server { # B
    server_name  b.example;
}

ここでは2つのrootディレクティブ(①, ②)が定義されている。①はA, Bどちらのブロックにも含まれていないため、どのコンテキストでも有効。
しかし、Aのブロックには別のrootディレクティブ②が定義されているため、Aのコンテキストでは②が優先される。
Bのブロックにはrootディレクティブが記述されていないため、①のrootディレクティブが有効。

user

ワーカプロセスの実行ユーザを指定する。デフォルトではnobodyユーザで起動する。
user ディレクティブを使用することで、特定のユーザでワーカを動作させることができる。

http

HTTPサーバに関連する設定を記述するにはhttpディレクティブを用いてhttpコンテキストを定義する。
nginx本体に関する設定を除き、ほとんどのHTTPサーバの動作に関連する設定は、このhttpディレクティブのブロック内に記述する。

include

共通設定を使用する場合や複数のサーバを設定する場合、設定ファイルを複数に分割することで管理しやすくなります。includeディレクティブを用いることで、複数に分割した設定ファイルを読み込んで使用できる。
パラメータにはファイル名またはファイルマスクを指定できる。(include /etc/nginx/conf.d/*.conf など)
ファイルは絶対パスあるいはnginx.confが配置されているパスからの相対パスで指定できる。

server

nginxでは使用するIPアドレス、ポート、ホスト名ごとに別々の設定を持つ複数のHTTPサーバを動作させることができ、これらはバーチャルサーバと呼ばれる。
バーチャルサーバは、それぞれ別々のHTTPサーバであるかのように動作し、それぞれ独立した設定を持っている。
バーチャルサーバはserverディレクティブで定義し、ブロック内に記述した設定がバーチャルサーバの設定として扱われる。

複数のバーチャルサーバを定義している場合、nginxは次の順番でどのバーチャルサーバが使用されるか決定します。
1. listenディレクティブのアドレスとポートに一致するバーチャルサーバを検索する
2. リクエストのHostヘッダがserver_nameディレクティブで指定したホストに一致したバーチャルサーバにリクエストを振り分ける
3. どのサーバにも一致しない場合デフォルトサーバにリクエストを振り分ける

ホスト名の一致は、完全一致、ワイルドカード正規表現の順番に評価されます。
どのバーチャルサーバにも一致しない場合はデフォルトサーバにリクエストが振り分けられます。
デフォルトサーバは設定ファイルの一番上に記述したバーチャルサーバが使用されますが、listenディレクティブにdefault_serverパラメータを使用することで明示的に指定できる。

server { # ①
    listen       80 default_server;
}
server { # ②
    listen       80;
    server_name  www.example.com;
}

上の場合、www.example.com 以外へのリクエストは①のサーバコンテキストにマッチする。

listen

バーチャルサーバが使用するアドレス、ポートはlistenディレクティブで指定する。
listenディレクティブではアドレス、ポートまたはUNIXドメインソケットファイルを指定できる。

listen *:8080;   #すべてのアドレスの8080番ポート
listen 8080;     #*:8080と同じ
listen 127.0.0.1:8080;    #ローカルアドレスの8080番ポート
listen localhost:8080;   #ホスト名で指定することもできる
listen unix:/var/run/nginx.sock;      #UNIXドメインソケットを指定

server_name

バーチャルサーバで使用するホスト名を指定するにはserver_nameディレクティブを使用する。
ホスト名を指定することで、80番ポートなど同じポート、アドレスで動作する複数のサーバを定義できる。

server_name example.com *.example.com;

server_nameディレクティブには複数のホスト名を指定できます。また、ホスト名の指定にはワイルドカードも使用できます。

server_name ~img\d+\.example\.com$;

ホスト名の指定には正規表現を使用することもできる。正規表現を使用する場合はチルダ(~)を先頭に付けて指定する。

root

公開するディレクトリを指定する。 nginxではrootディレクティブで指定したディレクトリのパスがそのURIのルートにマッピングされる。

root/var/www/html;

上の設定で http://www.example.com/images/example.png にリクエストされた場合、URIにおける絶対パス/images/example.png
ルートディレクトリは /var/www/html なので、ファイルシステム上で参照されるファイルは /var/www/html/images/example.png になる。
このようにファイルシステム上の絶対パスは、URIにおける絶対パスの前方にrootディレクティブに指定されたパスを結合したものになる。

nginxのDockerコンテナを使って静的コンテンツを表示する

Dockerfile

FROM nginx:1.13-alpine
COPY nginx.conf /etc/nginx/nginx.conf
RUN mkdir -p /var/www/html \
 && touch /var/www/html/index.html \
 && echo 'Hello' > /var/www/html/index.html

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;
    keepalive_timeout  65;
    server {
        listen 80;
        server_name www.nginx-example;
        root /var/www/html;
    }
}

Dockerfileをビルドし、nginxコンテナを8080番ポートで立ち上げる。

docker build -t $(REPOSITORY):$(VERSION) -f $(PWD)/Dockerfile $(PWD)
docker run -p 8080:80 $(REPOSITORY):$(VERSION)

/test.html でアクセスすると、Hello が表示される!