entrykitのテンプレート機能を使ってNginxのDockerfileを作ります。
Code
entrykitとは
コンテナ起動時にテンプレートファイルを元に設定ファイルを作ることができます。コンテナは設定ファイルに直接記載するのではなく、ポータビリティを高めるために環境変数で制御することを推奨しています。例えばNginxでは設定ファイルに直接環境変数を埋め込む仕組みがないため entrykitを使い制御します。
Nginxのイメージを取得
まずはDocker HubにあるNginxのイメージを取得し、設定ファイルの中身を確認したいと思います。
$ docker search --limit 5 nginx NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 12705 [OK] jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1745 [OK] richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 758 [OK] bitnami/nginx Bitnami nginx Docker Image 75 [OK] nginx/nginx-ingress NGINX Ingress Controller for Kubernetes 25 $ docker pull nginx $ docker container run -d -p 8080:80 nginx:latest
コンテナ内の設定ファイルを確認
Docker HubからPULLしてきたコンテナの設定ファイルを確認します。
# cat /etc/nginx/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_processes :Nginxのworkerプロセス数
- worker_connections:workerプロセスが開ける最大コネクション数
- keepalive_timeout:クライアントからの接続を維持する秒数
- gzip:レスポンスのGZIPを有効にするか
include /etc/nginx/conf.d/*.confに合致するファイルをロードししています。
# cat /etc/nginx/conf.d/default.conf server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
デフォルトのルートディレクトリは次のようになってます。
location / { root /usr/share/nginx/html; index index.html index.htm; }
環境変数を制御
entrykitのテンプレート機能(tmplファイル)を使い環境変数の制御を行います。entrykitを使うとDocker起動時にテンプレートファイルを元に設定ファイルのレンダリングが可能になります。
Dockerfileを作る際にはテンプレートファイルを次のようにコピーします。
COPY etc/nginx/nginx.conf.tmpl /etc/nginx/ COPY etc/nginx/conf.d/ /etc/nginx/conf.d/
entrykitでテンプレートから設定ファイルを生成します。renderで指定するパスは.tmplを付けずに完成後のパスを指定します。
ENTRYPOINT [ \ "render", \ "/etc/nginx/nginx.conf", \ "--", \ "render", \ "/etc/nginx/conf.d/upstream.conf", \ "--", \ "render", \ "/etc/nginx/conf.d/public.conf", \ "--" \ ]
設定ファイルを作成
entrykitのテンプレート機能を前提に設定ファイルを作ります。プロキシサーバとして使うので次のようにします。
ログ:etc/nginx/conf.d/log.conf
JSONフォーマットでログを出力できるよう定義します。
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/conf.d/upstream.conf.tmpl
リクエストを振り分ける先のバックエンドサーバを定義します。
upstream backend { server {{ var "BACKEND_HOST" }} max_fails={{ var "BACKEND_MAX_FAILS" | default 3 }} fail_timeout={{ var "BACKEND_FAIL_TIMEOUT" | default "10s" }}; }
- BACKEND_HOST:バックエンドの宛先
- BACKEND_MAX_FAILS:fail_timeoutの秒間の失敗回数上限
- BACKEND_FAIL_TIMEOUT:失敗したと判断する秒間
- default:デフォルト値
ルーティング- etc/nginx/conf.d/public.conf.tmpl
HTTPリクエストのルーティングを制御する設定ファイルを作ります。
server { listen {{ var "SERVER_PORT" | default "80" }} default_server; server_name {{ var "SERVER_NAME" | default "localhost" }}; charset utf-8; location / { proxy_pass http://backend; proxy_pass_request_headers on; proxy_set_header host $host; {{ if var "LOG_STDOUT" }} access_log /dev/stdout json; error_log /dev/stderr; {{ else }} access_log /var/log/nginx/backend_access.log json; error_log /var/log/nginx/backend_error.log; {{ end }} {{ if var "BASIC_AUTH_FILE" }} auth_basic "Restricted"; auth_basic_user_file {{ var "BASIC_AUTH_FILE" }}; {{ end }} } }
SERVER_PORT:デフォルト値80
proxy_pass :upstrem.confで定義したものを採用
LOG_STDOUT:環境変数に値が設定されていれば、アクセスログをファイルではなく標準出力にする
Dockerfileを作成する
それではDockerfileを作成します。環境変数はDockerfileではなくマニフェストファイルで与える方が好ましいですが、ここでは便器上Dockerfileに記載します。
# Dockerfile FROM nginx:latest RUN apt-get update RUN apt-get install -y wget RUN wget https://github.com/progrium/entrykit/releases/download/v0.4.0/entrykit_0.4.0_linux_x86_64.tgz RUN tar -xvzf entrykit_0.4.0_linux_x86_64.tgz RUN rm entrykit_0.4.0_linux_x86_64.tgz RUN mv entrykit /usr/local/bin/ RUN entrykit --symlink RUN rm /etc/nginx/conf.d/* COPY etc/nginx/nginx.conf.tmpl /etc/nginx/ COPY etc/nginx/conf.d/ /etc/nginx/conf.d/ ENTRYPOINT [ \ "render", \ "/etc/nginx/nginx.conf", \ "--", \ "render", \ "/etc/nginx/conf.d/upstream.conf", \ "--", \ "render", \ "/etc/nginx/conf.d/public.conf", \ "--" \ ] CMD ["nginx", "-g", "daemon off;"]
作成したDockerfileをビルドします。
$ docker image build -t nginx:01 . $ docker run -d -p 8080:80 nginx:01
Docker Compose
環境変数を使いNginxをプロキシサーバとしてExpressのアプリを可視化します。
version: '3' services: nginx: build: context: . dockerfile: Dockerfile image: nginx container_name: nginx ports: - 8888:80 environment: WORKER_PROCESSES: 2 WORKER_CONNECTIONS: 1024 KEEPALIVE_TIMEOUT: "65" GZIP: "on" BACKEND_HOST: app:3000 BACKEND_MAX_FAILS: 3 BACKEND_FAIL_TIMEOUT: 10s SERVER_PORT: 80 SERVER_NAME: todo_app_nginx LOG_STDOUT: "true" app: build: context: . dockerfile: Dockerfile-app image: app container_name: app ports: - 3000:3000 volumes: - ./myapp:/src command: [sh, -c, npm install && npm start]
$ docker-compose up --build
curlコマンドでlocalhost:8888でlocalhost:3000のExpressアプリを確認します。
$ curl http://localhost:8888/ <!DOCTYPE html> <html> <head> <title>Express</title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1>Express</h1> <p>Welcome to Express</p> </body> </html>
参考
docker の nginx イメージの設定ファイルを眺めながら、独自ページを表示します。 - Qiita
Docker/Kubernetes 実践コンテナ開発入門:書籍案内|技術評論社