ARM64 架构下编译支持 ngx_http_lua_module 的 Nginx —— Dockerfile 实践

🧾 ARM64 架构下编译支持 ngx_http_lua_module 的 Nginx —— Dockerfile 实践

一、📘 背景

ngx_http_lua_module 是 OpenResty 的核心模块之一,使 Nginx 可以直接执行 Lua 脚本,实现灵活的动态逻辑处理,例如:

  • 动态负载均衡
  • 请求内容过滤
  • 动态缓存控制
  • 自定义鉴权逻辑

官方的 Nginx 镜像默认 不包含 Lua 支持,因此需要通过编译源码的方式添加。


二、🧩 编译所需组件

编译时需要以下依赖:

依赖包 说明
build-essential 基础编译工具(gcc、make 等)
libpcre3 / libpcre3-dev Nginx 正则匹配模块依赖
zlib1g / zlib1g-dev Nginx 压缩模块依赖
openssl / libssl-dev HTTPS 支持
wget / git 下载源码
gettext-base 提供 envsubst 命令用于模板变量替换

额外依赖组件:

组件 说明
LuaJIT 高性能 Lua 虚拟机,Nginx 的 Lua 模块依赖它
lua-nginx-module Nginx 与 LuaJIT 的集成模块
lua-resty-core / lua-resty-lrucache OpenResty 常用 Lua 库(必须安装,否则报 “resty.core not found”)

三、🛠️ Dockerfile 分为两阶段

第一阶段:编译(builder)
第二阶段:运行时(runtime)

✅ 第一阶段:编译阶段(builder)

目标:在 arm64v8/ubuntu:22.04 上编译 Nginx + Lua 模块。

# =========================
# Builder
# =========================
FROM arm64v8/ubuntu:22.04 AS builder

RUN apt-get update && apt-get install -y \
    build-essential \
    libpcre3 libpcre3-dev \
    zlib1g zlib1g-dev \
    openssl libssl-dev \
    wget git ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /opt

ENV NGINX_VERSION=1.24.0
ENV LUAJIT_VERSION=2.1-20230410
ENV LUA_MODULE_VERSION=0.10.29

# 下载 Nginx
RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && \
    tar -zxvf nginx-${NGINX_VERSION}.tar.gz

# 编译 LuaJIT
RUN git clone https://github.com/openresty/luajit2.git -b v${LUAJIT_VERSION} && \
    cd luajit2 && make && make install

# 下载 lua-nginx-module
RUN git clone https://github.com/openresty/lua-nginx-module.git -b v${LUA_MODULE_VERSION}

# 下载并安装 lua-resty-core 和 lua-resty-lrucache
RUN git clone https://github.com/openresty/lua-resty-core.git /opt/lua-resty-core && \
    git clone https://github.com/openresty/lua-resty-lrucache.git /opt/lua-resty-lrucache && \
    mkdir -p /usr/local/share/lua/5.1/resty && \
    cp -r /opt/lua-resty-core/lib/resty/* /usr/local/share/lua/5.1/resty/ && \
    cp -r /opt/lua-resty-lrucache/lib/resty/* /usr/local/share/lua/5.1/resty/

# 环境变量
ENV LUAJIT_LIB=/usr/local/lib
ENV LUAJIT_INC=/usr/local/include/luajit-2.1

WORKDIR /opt/nginx-${NGINX_VERSION}

# 编译 Nginx + Lua 模块,路径改为 /etc/nginx
RUN ./configure \
	--prefix=/etc/nginx \
	--sbin-path=/etc/nginx/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
	--error-log-path=/etc/nginx/logs/error.log \
	--http-log-path=/etc/nginx/logs/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --with-cc-opt="-O2 -I${LUAJIT_INC}" \
    --with-ld-opt="-L${LUAJIT_LIB} -Wl,-rpath,${LUAJIT_LIB}" \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_realip_module \
    --with-threads \
    --with-http_stub_status_module \
    --add-module=/opt/lua-nginx-module \
    && make -j$(nproc) \
    && make install

✅ 第二阶段:运行时阶段(runtime)

目标:生成体积更小、运行时可直接使用的镜像。

# =========================
# Runtime image
# =========================
FROM arm64v8/ubuntu:22.04

RUN apt-get update && apt-get install -y \
    libpcre3 zlib1g openssl gettext-base \
    && rm -rf /var/lib/apt/lists/*

# 创建 nginx 用户和组
RUN groupadd -r nginx && useradd -r -g nginx nginx \
    && mkdir -p /var/log/nginx \
    && chown -R nginx:nginx /var/log/nginx

# 拷贝 Nginx 安装目录和 Lua 库
COPY --from=builder /etc/nginx /etc/nginx
COPY --from=builder /usr/local/lib/libluajit-5.1.so* /usr/local/lib/
COPY --from=builder /usr/local/share/lua/5.1 /usr/local/share/lua/5.1

ENV PATH=/etc/nginx/sbin:$PATH
ENV LD_LIBRARY_PATH=/usr/local/lib

# 暴露端口
EXPOSE 80 443

# 默认命令
CMD ["nginx", "-g", "daemon off;"]

四、📂 目录结构说明

编译完成后 /etc/nginx 目录结构:

/etc/nginx/
├── sbin/nginx                # Nginx 可执行文件
├── conf/nginx.conf           # 主配置文件
├── logs/                     # 日志目录
└── modules/                  # 可选的动态模块目录

Lua 相关模块位置:

/usr/local/share/lua/5.1/resty/
  ├── core/
  ├── lrucache/
  └── ...

五、⚙️ 验证 Lua 模块是否生效

进入容器后执行:

nginx -V 2>&1 | grep lua

输出应包含:

--add-module=/opt/lua-nginx-module

再创建测试配置 /etc/nginx/conf.d/lua_test.conf

server {
    listen 80;
    location /lua {
        default_type text/plain;
        content_by_lua_block {
            ngx.say("Hello from Lua in ARM64 Nginx!")
        }
    }
}

启动 nginx 后访问 /lua,应输出:

Hello from Lua in ARM64 Nginx!

六、🧰 常见问题与解决方案

错误信息 原因 解决方案
ngx_http_lua_module requires LuaJIT 2.x LuaJIT 未安装或版本错误 确认 LUAJIT_INCLUAJIT_LIB 环境变量设置正确
resty.core not found 没有安装 lua-resty-core 手动拷贝 core 与 lrucache 到 /usr/local/share/lua/5.1/resty
nginx: [emerg] getpwnam("nginx") failed 配置中使用 user nginx; 但用户不存在 Dockerfile 中添加 useradd -r nginx
could not open error log file /var/log/nginx 目录不存在或无权限 创建目录并设置权限
/usr/sbin/nginx: not found PATH 或编译路径不一致 使用 --sbin-path=/etc/nginx/sbin/nginx 并更新 PATH

七、🚀 构建与运行

# 构建镜像
docker build -t nginx-lua:arm64 .

# 启动容器
docker run -d -p 8080:80 nginx-lua:arm64

# 测试访问
curl http://localhost:8080/lua

输出:

Hello from Lua in ARM64 Nginx!

八、🌟 进阶优化建议

  1. 可选优化:多阶段裁剪镜像

    • 使用 FROM arm64v8/alpine 作为 runtime 基础镜像,体积更小;
    • 但需要手动安装 musl 编译 LuaJIT,过程略复杂。
  2. 可选优化:OpenResty 替代方案

    • 如果目标仅是使用 Lua,可以直接用 openresty/openresty:arm64 镜像;
    • 该镜像内置所有 Lua 模块,无需自己编译。
  3. 环境变量模板渲染

    • 可使用 envsubst 在容器启动时自动替换 Nginx 配置中的变量。

✅ 总结

模块 路径 说明
Nginx 主目录 /etc/nginx 标准安装目录
Nginx 二进制 /etc/nginx/sbin/nginx 执行文件路径
LuaJIT 库 /usr/local/lib/libluajit-5.1.so 动态链接库
Lua 脚本库 /usr/local/share/lua/5.1/resty/ Lua 模块代码
日志路径 /var/log/nginx/ 需确保 nginx 用户可写
posted @ 2025-10-31 16:06  槑孒  阅读(9)  评论(0)    收藏  举报