如何构建支持 ngx_http_lua_module 的 ARM64 架构 Nginx Dockerfile?

摘要:一、📘 背景 ngx_http_lua_module 是 OpenResty 的核心模块之一,使 Nginx 可以直接执行 Lua 脚本,实现灵活的动态逻辑处理,例如: 动态负载均衡 请求内容过滤 动态缓存控
一、📘 背景 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_INC 与 LUAJIT_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! 八、🌟 进阶优化建议 可选优化:多阶段裁剪镜像 使用 FROM arm64v8/alpine 作为 runtime 基础镜像,体积更小; 但需要手动安装 musl 编译 LuaJIT,过程略复杂。 可选优化:OpenResty 替代方案 如果目标仅是使用 Lua,可以直接用 openresty/openresty:arm64 镜像; 该镜像内置所有 Lua 模块,无需自己编译。 环境变量模板渲染 可使用 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 用户可写