为 Docker 中的 Nginx 启用 Brotli 压缩算法

为了节省服务器带宽,加快页面速度,准备为 Nginx 启用 Brotli 插件。我发现都已经 1.21.6 版本了,Brotli 作为一个非常常用的无损压缩插件,仍然没有被包含到官方的 Nginx docker 镜像中,那么我们要使用只能自己动手了。

一、成果

我把构建好的镜像推送到了 Github 的 Docker registry 里,懒得折腾的可以直接使用。

可以通过以下语句拉取。

1
docker pull ghcr.io/zvonimirsun/nginx-brotli:stable-alpine

我这边选用了最新 stable 版本的 Nginx,因为不会一直关注 Nginx 版本,更新可能会不及时。

二、解决方案

总的来说就是通过对应版本的 Nginx 编译google/ngx_brotli,然后将编译出来的插件 so 文件塞到官方镜像中,这样我们就能够动态加载此模块了。

针对 Dockerfile 一点说明:

  • build-base: 添加编译相关工具
  • git: 用于克隆google/ngx_brotli
  • pcre-dev: http rewrite 模块需要用到
  • openssl-dev: ssl 模块需要用到
  • zlib-dev: gzip 模块需要用到
  • linux-headers: with-file-ato 需要用到
  • brotli-dev: 用于编译 brotli 模块
  • configure 参数完全使用了官方镜像参数,仅添加了 add-dynamic-module 用于添加 brotl。可以执行 docker run --rm nginx:stable-alpine nginx -V 查看最新的编译参数。

Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
FROM nginx:stable-alpine-slim AS builder

ARG NGINX_VERSION

WORKDIR /root/

RUN apk add --update --no-cache build-base git pcre-dev openssl-dev zlib-dev linux-headers brotli-dev \
&& wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \
&& tar zxf nginx-${NGINX_VERSION}.tar.gz \
&& git clone https://github.com/google/ngx_brotli.git \
&& cd ngx_brotli \
&& git submodule update --init --recursive \
&& cd ../nginx-${NGINX_VERSION} \
&& CONFIG=`nginx -V 2>&1 | tr '\n' ' ' | sed 's/^.* configure arguments: //g'` \
&& echo "./configure --add-dynamic-module=../ngx_brotli $CONFIG" > configure.sh \
&& chmod +x configure.sh \
&& ./configure.sh \
&& make modules

FROM nginx:stable-alpine

ENV TIME_ZONE=Asia/Shanghai

RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone

COPY --from=builder /root/nginx-${NGINX_VERSION}/objs/ngx_http_brotli_filter_module.so /usr/lib/nginx/modules/
COPY --from=builder /root/nginx-${NGINX_VERSION}/objs/ngx_http_brotli_static_module.so /usr/lib/nginx/modules/

三、启用 Brotli

确保使用了我的镜像或上文的 Dockerfile 构建出的镜像。此时镜像中已经添加了 Brotli 的模块文件,可以动态引入。

在 nginx.conf 开头添加

1
2
load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so;
load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;

http部分中添加以启用,gzip 和 Brotli 可以共存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# brotli
brotli on;
brotli_comp_level 6;
brotli_buffers 16 8k;
brotli_min_length 20;
brotli_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/vnd.ms-fontobject
application/wasm
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/bmp
image/svg+xml
text/cache-manifest
text/calendar
text/css
text/javascript
text/markdown
text/plain
text/xml
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;

通过nginx -t检查下配置无误后,通过nginx -s reload应用配置即可。