NginxのDockerイメージを作成

はじめに

kubernetesAPIサーバを構築している中で APIの前にNginxを挟む構成にすることで恩恵が受けられることわかった。

構成

  • Nginxコンテナ -> APIコンテナ (1つのPodで記載)

恩恵

  • アクセスログの取得が簡単になる
  • キャッシュ制御ができる → APIサーバの負荷軽減
  • アプリケーションに手を加えず、任意にルーティングできる。

Kubenetesを使うためにはDockerイメージが必要なので作った。

学べたこと

Nginxは環境変数でパラメータを置き換える仕組みがない

設定ファイルを環境変数でパラメータを置き換えて起動したかったが、
Nginxに環境変数を置き換える仕組みがない。
そのため、コンテナ起動時にenvsubstコマンドを使って、
テンプレートファイルから設定ファイルを生成する必要があった。

公式イメージの19.1からconf.dのファイルなら環境変数値で置き換えることができる

公式イメージの19.1のバージョンから
/etc/nginx/templatesフォルダに格納されたtemplateファイルは、
envsubstが実行され、container起動時にコピーされるようになった。

※ただし、/etc/nginx/nginx.confの設定は、envsubstを使用して置き換える必要がある。

作成したファイル


結果、以下の設定を行って動いた。

nginx.conf.template

user nginx;
worker_processes $WORKER_PROCESSES;

error_log /var/log/nginx/error.log warn;
pid       /var/run/nginx.pid;

events {
  worker_connections $WORKER_CONNECTIONS;
}

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 $KEEPALIVE_TIMEOUT;

  gzip $GZIP;

  include /etc/nginx/conf.d/*.conf;
}

etc/nginx/templates/log.conf.template

log_format json '{'
                '"time": "$time_iso8601",'
                '"remote_addr": "$remote_addr",'
                '"request": "$request",'
                '"request_method": "$request_method",'
                '"request_length": "$request_length",'
                '"request_uri": "$request_uri",'
                '"uri": "$uri",'
                '"query_string": "$query_string",'
                '"status": "$status",'
                '"bytes_sent": "$bytes_sent",'
                '"body_bytes_sent": "$body_bytes_sent",'
                '"referer": "$http_referer",'
                '"useragent": "$http_user_agent",'
                '"forwardedfor": "$http_x_forwarded_for",'
                '"request_time": "$request_time",'
                '"upstream_response_time": "$upstream_response_time",'
                '}';

etc/nginx/templates/public.conf.template

server {
    listen $SERVER_PORT;
    server_name $SERVER_NAME;
    charset utf-8;

    location / {
        proxy_pass http://backend;
        proxy_pass_request_headers on;
        proxy_set_header host $host;

        access_log /var/log/nginx/backend_access.log json;
        error_log  /var/log/nginx/backend_error.log;
    }

}

etc/nginx/templates/upstream.conf.template

upstream backend {
    server $BACKEND_HOST max_fails=$BACKEND_MAX_FAILS fail_timeout=$BACKEND_FAIL_TIMEOUT;
}

Dockerfile

FROM nginx:1.21.5

# Set debian default locale to ja_JP.UTF-8
RUN apt-get update && \
    apt-get install -y locales && \
    apt-get install -y wget && \
    apt-get install -y gettext-base && \
    rm -rf /var/lib/apt/lists/* && \
    echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8

COPY etc/nginx/nginx.conf.template /etc/nginx/nginx.conf.template
COPY etc/nginx/templates/ /etc/nginx/templates/

CMD envsubst '$WORKER_PROCESSES $WORKER_CONNECTIONS $KEEPALIVE_TIMEOUT $GZIP' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;'

docker-compose.yml

version: '3.8'
services:
  nginx:
    build: ./
    environment:
      WORKER_PROCESSES: 2
      WORKER_CONNECTIONS: 1024
      KEEPALIVE_TIMEOUT: 65
      GZIP: "on"
      BACKEND_HOST: 127.0.0.1
      BACKEND_MAX_FAILS: 3
      BACKEND_FAIL_TIMEOUT: 10s
      SERVER_PORT: 80
      SERVER_NAME: todo_app_nginx
    container_name: nginx