nginx 自从 1.9.11 以后就支持动态加载模块了, 不需要重新编译 nginx, 只需要将模块编译为 so 然后在 nginx 的配置文件中加载就行。
nginx 版本可用 nginx -v 查看
root@aliyun:/# nginx -v nginx version: nginx/1.17.9
可以得知目前 docker 容器内的 nginx 版本为 1.17.9, 下载 nginx 源码以及模块源码并解压
wget https://github.com/nginx/nginx/archive/release-1.17.9.tar.gz tar -xvf release-1.17.9.tar.gz
git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
Nginx 模块源码中存在着 config 脚本文件, 静态模块和动态模块的配置文件时不同的。新格式的 config 脚本是同时兼容动态模块和静态模块的, 模块的 config脚本还是旧的格式, 则需要根据文档去转换。
有些模块是无法被配置为动态模块的。
新式配置脚本样例
ngx_addon_name=ngx_http_hello_world_module if test -n "$ngx_module_link"; then ngx_module_type=HTTP ngx_module_name=ngx_http_hello_world_module ngx_module_srcs="$ngx_addon_dir/ngx_http_hello_world_module.c" . auto/module else HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c" fi
旧式配置脚本样例
ngx_addon_name=ngx_http_response_module HTTP_MODULES="$HTTP_MODULES ngx_http_response_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_response_module.c"
转换的方法见: https://www.nginx.com/resources/wiki/extending/converting/
本文提及的 ngx_http_substitutions_filter_module 使用的新式脚本, 因此可以直接被编译为动态模块无需配置。
先安装编译时依赖的库(需要安装的库可能不止这些, 跟着报错找的)
sudo apt install make gcc zlib1g-dev libpcre3-dev libssl-dev
由于新版 nginx 目录结构的改版, 源码的目录结构和旧版本的不太一样:
configure 脚本从根目录移到了 auto 目录下
cd 进 nginx 源码目录后使用 --with-compat 和 --add-dynamic-module 参数来配置编译环境
./auto/configure --with-compat --add-dynamic-module=../ngx_http_substitutions_filter_module make modules
编译出来的模块在 objs\ngx_http_subs_filter_module.so
根据官方文档来讲, 只需要添加两个参数就可以编译动态模块了。但是, 实际环境中 nginx 的编译参数可能是很复杂的, 如果发现编译出来的模块无法正常加载, 可以考虑用 nginx -V 查看编译 nginx 时使用的参数, 将参数加入 configure 命令后再次尝试编译加载模块
我使用的 nginx docker 镜像为 nginx 官方的镜像, 模块被存放在 /usr/lib/nginx/modules 下, 将模块挂载入 container 后, 修改 nginx 配置文件 /etc/nginx/nginx.conf, 加入
load_module modules/ngx_http_subs_filter_module.so;
重载容器中的 nginx 配置即可使用新模块
修改完配置文件后可以在 maps 中看到 so 已被加载