共计 4815 个字符,预计需要花费 13 分钟才能阅读完成。
Nginx 官方镜像只包含了官方版本所支持的模块,第三方模块并未包含其中,需要自己构建Docker镜像,只是网上很多教程都采用了自己编写的 Dokcerfile 拉取的是 Github 存储库最原始的代码进行编译感觉不太稳定。Nginx Docker 官方仓库提供了 pkg-oss 包源添加第三方模块的方法,这个包源是 Nginx 官方维护的有一定的稳定性保证。
构建Nginx自定义第三方模块镜像
Github 官方教程,在教程官方列出了可以直接从官方维护的 pkg-oss 拉取的第三方模块如下:
/pkg-oss $ LC_ALL=C make -C debian list-all-modules
make: Entering directory '/pkg-oss/debian'
auth-spnego 1.1.1-1
brotli 1.0.0-1
encrypted-session 0.09-1
fips-check 0.1-1
geoip 1.25.1-1
geoip2 3.4-1
headers-more 0.34-1
image-filter 1.25.1-1
lua 0.10.25-1
modsecurity 1.0.3-3
ndk 0.3.2-1
njs 0.8.0-1
opentracing 0.29.0-1
passenger 6.0.18-1
perl 1.25.1-1
rtmp 1.2.2-1
set-misc 0.33-1
subs-filter 0.6.4-1
xslt 1.25.1-1
make: Leaving directory '/pkg-oss/debian'
官方并未发布有关Docker镜像,需要自行进行构建编译,在教程中官方也提供了相关 Dockerfile 并提供了基于 alpine 和 debian 两个版本,下面是我根据官方 alpine 版本的 Dockerfile 添加代码 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
替换清华的镜像源提高构建速度。
ARG NGINX_FROM_IMAGE=nginx:mainline-alpine
FROM ${NGINX_FROM_IMAGE} as builder
ARG ENABLED_MODULES
RUN set -ex \
&& if [ "$ENABLED_MODULES" = "" ]; then \
echo "No additional modules enabled, exiting"; \
exit 1; \
fi
# COPY ./ /modules/
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
RUN set -ex \
&& apk update \
&& apk add linux-headers openssl-dev pcre2-dev zlib-dev openssl abuild \
musl-dev libxslt libxml2-utils make mercurial gcc unzip git \
xz g++ coreutils \
# allow abuild as a root user \
&& printf "#!/bin/sh\\nSETFATTR=true /usr/bin/abuild -F \"\$@\"\\n" > /usr/local/bin/abuild \
&& chmod +x /usr/local/bin/abuild \
&& hg clone -r ${NGINX_VERSION}-${PKG_RELEASE} https://hg.nginx.org/pkg-oss/ \
&& cd pkg-oss \
&& mkdir /tmp/packages \
&& for module in $ENABLED_MODULES; do \
echo "Building $module for nginx-$NGINX_VERSION"; \
if [ -d /modules/$module ]; then \
echo "Building $module from user-supplied sources"; \
# check if module sources file is there and not empty
if [ ! -s /modules/$module/source ]; then \
echo "No source file for $module in modules/$module/source, exiting"; \
exit 1; \
fi; \
# some modules require build dependencies
if [ -f /modules/$module/build-deps ]; then \
echo "Installing $module build dependencies"; \
apk update && apk add $(cat /modules/$module/build-deps | xargs); \
fi; \
# if a module has a build dependency that is not in a distro, provide a
# shell script to fetch/build/install those
# note that shared libraries produced as a result of this script will
# not be copied from the builder image to the main one so build static
if [ -x /modules/$module/prebuild ]; then \
echo "Running prebuild script for $module"; \
/modules/$module/prebuild; \
fi; \
/pkg-oss/build_module.sh -v $NGINX_VERSION -f -y -o /tmp/packages -n $module $(cat /modules/$module/source); \
BUILT_MODULES="$BUILT_MODULES $(echo $module | tr '[A-Z]' '[a-z]' | tr -d '[/_\-\.\t ]')"; \
elif make -C /pkg-oss/alpine list | grep -E "^$module\s+\d+" > /dev/null; then \
echo "Building $module from pkg-oss sources"; \
cd /pkg-oss/alpine; \
make abuild-module-$module BASE_VERSION=$NGINX_VERSION NGINX_VERSION=$NGINX_VERSION; \
apk add $(. ./abuild-module-$module/APKBUILD; echo $makedepends;); \
make module-$module BASE_VERSION=$NGINX_VERSION NGINX_VERSION=$NGINX_VERSION; \
find ~/packages -type f -name "*.apk" -exec mv -v {} /tmp/packages/ \;; \
BUILT_MODULES="$BUILT_MODULES $module"; \
else \
echo "Don't know how to build $module module, exiting"; \
exit 1; \
fi; \
done \
&& echo "BUILT_MODULES=\"$BUILT_MODULES\"" > /tmp/packages/modules.env
FROM ${NGINX_FROM_IMAGE}
COPY --from=builder /tmp/packages /tmp/packages
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
RUN set -ex \
&& . /tmp/packages/modules.env \
&& for module in $BUILT_MODULES; do \
apk add --no-cache --allow-untrusted /tmp/packages/nginx-module-${module}-${NGINX_VERSION}*.apk; \
done \
&& rm -rf /tmp/packages
上面的 Dockerfile 读取docker 构建参数 ENABLED_MODULES 在上面的 pkg-oss 列表中的地方模块都可以在这个参数中指定,如 ENABLED_MODULES="ndk lua"
的形式,这里我这只需添加 brotli 这个第三方模块,可以使用两种构建命令,一种是在 Dockerfile 目录下执行 docker build
命令如下:
docker build --build-arg ENABLED_MODULES="brotli" -t my-nginx-with-lua .
其中-t 后面可以自己指定构建 Tag。还有一种方法是在 Docker Compose 中进行构建,这种方法更方便管理。运行参数暂时不考虑,添加如下 docker-compose.yaml 文件:
version: "3.3"
services:
nginx:
build:
context: ./
args:
ENABLED_MODULES: brotli
image: my-nginx-with-lua
其中context
可以根据你的 docker-compose.yaml 和 Dockerfile 文件的相对路径自行修改。 ENABLED_MODULES
指定要编译的第三方模块,可以添加多个第三方模块,修改为 ENABLED_MODULES: "ndk lua"
这种形式就可以了。然后在目录下执行以下命令。
docker compose build nginx
示例中会构建包含 brotli 第三方插件的 docker nginx 镜像,可以在本地直接使用可以使用 docker push my-nginx-with-lua
其中my-nginx-with-lua
为你自定义的tag名称或者 image名称推送到阿里云镜像仓库中分发给使用。下面演示在本地使用brotli 第三方插件。
Nginx中配置使用 brotli
使用第三方模块需要在配置文件中导入,以下是 nginx 开启 brotli 的简化配置。
# 载入 brotli 模块
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
worker_processes auto;
events {
worker_connections 1024;
}
http {
# 在http节开启 brotli 压缩
brotli_static on;
brotli on;
brotli_types *;
brotli_comp_level 6;
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
总结
Nginx 官方 Docker 仓库 提供这种配置方法可以安装多个第三方插件,并且插件的包源是官方维护的一定程度上保证了其稳定性。可以在开发主机上构建后再编译发布到镜像仓库中,自己维护一个版本使用。也可以随时跟上官方更新最新的 Nginx 版本。