将njs模块添加到Openresty的Docker镜像中

如果想要在nginx中使用Lua,Openresty是首选,但最近也有一种名为njs的嵌入式语言可在nginx中使用。

nginx/njs:官方只读镜像,每小时更新的http://hg.nginx.org/njs/。

njs是Nginx公司在2016年推出的一种Javascript子集语言。与Lua一样,njs允许动态更改配置文件。尽管在功能丰富性方面不如Lua,但如果不涉及过于复杂的任务,njs也是一种容易上手的选择。此外,作为Web工程师,我认为与Lua相比,我们更熟悉Javascript的语法,所以在不想付出学习Lua的成本时,njs是一个可行的选择。(由于我主要从事后端开发,对Javascript只是一种兴趣爱好级别的了解,所以我对Lua和Javascript都只能写出差不多水平的代码。)

因此,我想比较Lua和NJS并进行了一些调查,但我没有找到能够同时尝试Lua和NJS的环境,所以我自己用Docker创建了一个。

openresty/openresty – Docker Hub

openresty/docker-openresty: Docker tooling for OpenResty

Compiling NGINX module as dynamic module for use in docker

我根据上述主要内容的文章,参考了openresty镜像并搭建了相应的环境。

在构建/安装nginx动态模块时需要注意几点:必须使用与Nginx本体相同的版本进行构建,并且./configure命令也必须相同。此外,需要在配置文件的早期阶段加载load_module模块。

FROM openresty/openresty:1.15.8.2-alpine-fat AS builder

# Our NCHAN version
ENV NGINX_VERSION 1.15.8
ENV NJS_VERSION 0.2.8

# For latest build deps, see https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile
RUN apk add --no-cache --virtual .build-deps \
  gcc \
  libc-dev \
  make \
  openssl-dev \
  pcre-dev \
  zlib-dev \
  linux-headers \
  curl \
  gnupg \
  libxslt-dev \
  gd-dev \
  geoip-dev

# Download sources
RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -O nginx.tar.gz && \
    wget "https://github.com/nginx/njs/archive/${NJS_VERSION}.tar.gz" -O njs.tar.gz

# Reuse same cli arguments as the nginx:alpine image used to build
RUN CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
    tar -zxC /usr/local -f nginx.tar.gz && \
    tar -xzvf "njs.tar.gz" -C /usr/local/nginx-${NGINX_VERSION} && \
    NJSDIR="/usr/local/nginx-${NGINX_VERSION}/njs-${NJS_VERSION}/nginx" && \
    cd /usr/local/nginx-${NGINX_VERSION} && \
   ./configure --with-compat $CONFARGS --add-dynamic-module=$NJSDIR && \
    make modules && make install

FROM openresty/openresty:1.15.8.2-6-alpine
# Extract the dynamic module NCHAN from the builder image
COPY --from=builder /usr/local/nginx/modules/ngx_http_js_module.so /usr/local/openresty/nginx/modules/ngx_http_js_module.so

COPY nginx.conf   /usr/local/openresty/nginx/conf/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]
# nginx.conf  --  docker-openresty
#
# This file is installed to:
#   `/usr/local/openresty/nginx/conf/nginx.conf`
# and is the file loaded by nginx at startup,
# unless the user specifies otherwise.
#
# It tracks the upstream OpenResty's `nginx.conf`, but removes the `server`
# section and adds this directive:
#     `include /etc/nginx/conf.d/*.conf;`
#
# The `docker-openresty` file `nginx.vh.default.conf` is copied to
# `/etc/nginx/conf.d/default.conf`.  It contains the `server section
# of the upstream `nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

load_module modules/ngx_http_js_module.so;

events {
    worker_connections  1024;
}


http {
    include       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  logs/access.log  main;

    # See Move default writable paths to a dedicated directory (#119)
    # https://github.com/openresty/docker-openresty/issues/119
    client_body_temp_path /var/run/openresty/nginx-client-body;
    proxy_temp_path       /var/run/openresty/nginx-proxy;
    fastcgi_temp_path     /var/run/openresty/nginx-fastcgi;
    uwsgi_temp_path       /var/run/openresty/nginx-uwsgi;
    scgi_temp_path        /var/run/openresty/nginx-scgi;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
# load_module modules/ngx_http_js_module.so;
js_include hello_world.js;

server {
    # see: http://nginx.org/en/docs/http/server_names.html
    server_name _;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /hello {
        default_type text/html;
        content_by_lua '
            ngx.say("<p>Hello World</p>")
        ';
    }

    location /js_hello {
        js_content hello;
    }
}

由于njs无法直接在配置文件中编写JavaScript代码,因此需要将代码分离到其他文件中。

function hello(r) {
    r.return(200, "Hello njs!");
}

在构建此容器的状态下,我们可以使用自定义的nginx.conf和JavaScript文件进行挂载,以便在运行docker时使用。

# docker build
$ docker build -t njs .

# docker run
$ docker run -d --rm --name=my-njs -p 8082:80 \
      -v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf  \
      -v $(pwd)/hello_world.js:/usr/local/openresty/nginx/conf/hello_world.js \
      -it njs

我們將訪問作為動作驗證啟動的Docker容器。

$ curl 192.168.99.100:8082/hello
<p>Hello World</p>

$ curl 192.168.99.100:8082/js_hello
Hello njs!

没有出现错误,而是正确返回了响应。

以下是有关如何在Openresty中引入njs动态模块的提示。
本次使用的文件列表在这里。

    gist
bannerAds