尧图精选

基于ARM64与docker-compose的tengine 3.1.0一键离线部署工具

🕒 发布时间:2026/10/1 5:18:34 📁 来源:尧图网络
简介针对ARM64架构CPU的运维与开发人员可直接使用docker-compose一键离线部署tengine 3.1.0无需联网即可交付反向代理与负载均衡环境。资源共14个文件涵盖docker-compose编排文件、Dockerfile构建脚本、conf配置模板、html静态页面、日志目录及README说明压缩包整体34.54MB结构精简便于分发至目标服务器。部署后支持灵活修改代理配置同时将配置文件、日志与静态资源目录持久化后续更新规则或站点内容无需重建容器显著降低ARM64内网环境下的维护成本。包内附构建脚本与默认配置示例适合需要国产化ARM平台落地nginx服务的运维工程师参考。目前已有101人学习离线交付场景下具备较强的实用价值。1. 一句话讲清楚这套离线部署工具包到底解决什么一个做政企项目的朋友半夜找我抱怨生产网是物理隔离的没有外网手中的服务器还是麒麟 V10 ARM64 的鲲鹏 CPU。他想上 nginx但对方明说“最好用 tengine”还要一小时内跑起来。结果他拿 U 盘拷了 x86 的 docker 镜像和 Python 版 docker-compose上了机器全是exec format error。这就是「基于 ARM64 架构 CPU 使用 docker-compose 一键离线部署 tengine 3.1.0 工具」要解决的问题把镜像、compose 编排、二进制工具和部署脚本打成一个自包含的离线部署包拷到 ARM64 内网机器上执行一条./deploy.shtengine 3.1.0 就起来了。适合部署环境无外网的团队也适合经常对接国产化 ARM64 服务器的一线交付人员。下文按「选型依据 → 打包过程 → 部署脚本 → 踩坑实录 → 验证技巧」展开每段命令都能直接抄。2. 为什么是 ARM64 tengine compose 这个组合2.1 ARM64 和 x64 到底差在哪镜像为什么不能通用ARM64 指的是基于 ARM 的 64 位指令集架构也就是业界常说的 AArch64对应 ARMv8-A 指令集大家手机里经常看到arm64-v8a这个名词就是这一档。x64 则指 x86-64Intel、AMD 两家服务器芯片的主流指令集。指令集不同所有二进制机器码都不通用这是离线部署里第一个绕不过去的坎。实际操作中最常见的翻车现场如下在 x86 机器上docker pull nginx和docker save -o nginx.tar把 tar 包传到 ARM64 机器上docker load后一docker run立刻报exec format error。原因很简单镜像里的二进制是为 x86-64 编译的ARM64 内核执行不了。反过来也一样鲲鹏 920、飞腾 FT-2000 这类 CPU 上必须用 arm64 版本的镜像。qemu 模拟 arm64是另一种思路在 x86 机器上用 qemu 的用户态模拟配合 binfmt_misc让 Docker 直接跑 arm64 的容器。它能帮你绕过架构差异但我不建议把这套方案用在生产离线部署上。qemu 用户态模拟没有 KVM 硬件加速性能损失非常夸张CPU 密集的任务能慢到让人怀疑机器坏了。而且模拟环境下的指令集行为、内存模型和真机有细微差别某些依赖 CPU 特性做优化的程序比如指令集检测、JIT 类服务在模拟器里能跑搬到真机会翻车。正确做法是在真实的 ARM64 环境上准备离线包把架构匹配直接做成硬约束。2.2 为什么选 tengine 3.1.0 而不是裸 nginxtengine 是阿里发起维护的 nginx 增强版3.1.0 这个版本在配置语法和模块体系上和 nginx 保持高度兼容同时又补了几个对一线部署很实用的能力动态模块加载 DSO、内置的健康检查针对上游节点做主动探测、更细粒度的 error_log 级别控制等。离线部署场景下我最看重的是 DSO 特性。生产环境总会碰到临时加一个模块的需求而 tengine 可以编译出.so动态模块后续加模块只需要在配置里加一条load_module不用重新编译整个二进制。这点在不能随便拉外网装编译依赖的隔离环境里价值极大。另外一个现实考虑是国内大量存量项目的 nginx 配置都是按 tengine 的变体写法维护的从 nginx 迁移到 tengine 时配置几乎不用改团队内的历史经验能复用。2.3 docker-compose 选 v2 版单文件二进制的三个理由离线环境里安装 docker-compose 是个容易踩坑的环节。旧版 v1 是 Python 编写的部署它需要 pip、需要一堆依赖包docker、requests、websocket-client、PyYAML等。在没有外网的机器上补齐这一套 Python 依赖是非常折磨人的事版本稍微不对就会起不来。docker-compose v2 改成了 Go 写的单文件二进制官方仓库里直接提供docker-compose-linux-aarch64ARM64 架构的编译产物。离线部署时只需要把这样一个文件拷到目标机器的/usr/local/bin/下chmod x就能用一个文件解决全部依赖问题。以目前常见的 2.32.1 版本为例它不再依赖 Python 运行时启动速度也比 v1 快不少。需要提醒的是v1 时期的命令是docker-compose带连字符v2 时期官方建议的命令是docker compose子命令形式。但 v2 二进制也保留了对旧命令的兼容你把它安装成docker-compose这个名字后新旧两种写法都能用。后续的部署脚本里我会同时兼容这两种调用方式避免交付现场因为命令形态不一致而卡壳。3. 离线部署包的制作流程从镜像构建到一键脚本3.1 离线部署包的整体目录结构常见的做法是准备一台联网的 ARM64 机器比如同架构的测试服务器、开发板作为打包机把下面这套目录结构整个拷到目标机器上。这个目录就叫“工具”本身自带镜像、compose 文件、配置和部署入口。offline-tengine/ ├── deploy.sh # 一键部署入口 ├── sha256sums.txt # 镜像与二进制校验清单 ├── images/ │ └── tengine-arm64-3.1.0.tar ├── bin/ │ └── docker-compose-linux-aarch64 ├── compose/ │ ├── docker-compose.yml │ └── .env └── conf/ ├── nginx.conf └── mime.types目录设计说明images放导出后的镜像 tarbin放 docker-compose 的 ARM64 二进制conf放 tengine 的配置compose放编排文件。把校验清单sha256sums.txt放在最外层配合部署脚本做完整性校验。整个包不需要 root 以外的特殊权限拷到目标机器后目录权限只要可读、可执行即可。3.2 构建 tengine 3.1.0 的 ARM64 镜像并导出如果目标内网能访问内部镜像仓库直接docker pull tengine:3.1.0然后docker save即可。但很多内网连内部仓库都没有所以我更常用的做法是准备一个 Dockerfile在打包机上自己编译出 tengine 3.1.0 的 ARM64 镜像。以下是一个可用于离线打包的最小 DockerfileFROM debian:bullseye-slim-arm64v8 # 安装编译依赖打包机需要外网 RUN apt-get update apt-get install -y \ wget build-essential libpcre3-dev libssl-dev zlib1g-dev \ rm -rf /var/lib/apt/lists/* # 下载并编译 tengine 3.1.0 ENV TENGINE_VERSION3.1.0 RUN wget -q https://tengine.taobao.org/download/tengine-${TENGINE_VERSION}.tar.gz \ tar -xzf tengine-${TENGINE_VERSION}.tar.gz \ cd tengine-${TENGINE_VERSION} \ ./configure \ --prefix/usr/local/tengine \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_realip_module \ --with-http_slice_module \ --with-http_gzip_static_module \ --with-threads \ --with-file-aio \ make -j$(nproc) \ make install \ rm -rf /deps /tengine-* # 前台运行容器退出时能正确收到信号 CMD [/usr/local/tengine/sbin/nginx, -g, daemon off;]构建命令docker build -t tengine:3.1.0-arm64 . docker save -o images/tengine-arm64-3.1.0.tar tengine:3.1.0-arm64参数说明FROM debian:bullseye-slim-arm64v8显式指定 ARM64 架构的基础镜像避免 Docker 在多架构环境下自动拉到 x86 版本。编译参数里--with-http_ssl_module是 HTTPS 服务的硬需求--with-http_stub_status_module用于暴露/nginx_status给监控系统采集--with-http_realip_module解决反代场景下获取真实客户端 IP 的问题--with-http_slice_module则让大文件响应支持切片适合视频或大附件下载场景。make -j$(nproc)表示按 CPU 核数并行编译在鲲鹏多核机器上能显著缩短构建时间。导出这一步才是离线部署的核心动作。docker save打出来的 tar 包会保留完整的镜像分层和架构元数据目标机器上docker load后可以直接用不需要任何联网操作。3.3 编写 compose 编排文件tengine 运行起来至少需要三个目录日志目录、网站根目录、配置文件目录。为了让宿主机方便查看日志和修改配置我用挂载方式把这些目录映射出来services: tengine: image: tengine:3.1.0-arm64 container_name: tengine-3-1-0 restart: unless-stopped ports: - 80:80 - 443:443 volumes: - ./conf/nginx.conf:/usr/local/tengine/conf/nginx.conf:ro - ./conf/mime.types:/usr/local/tengine/conf/mime.types:ro - ../data/html:/usr/local/tengine/html - ../data/logs:/usr/local/tengine/logs environment: - TZAsia/Shanghai healthcheck: test: [CMD, /usr/local/tengine/sbin/nginx, -t] interval: 30s timeout: 5s retries: 3这里的.env文件可以定义TENGINE_PORT80这样的变量compose 会自动读取。restart: unless-stopped保证机器断电重启后容器自动拉起这在离线无人值守的环境里很重要。healthcheck里使用nginx -t做配置检查虽然不真正发起网络探测但能第一时间发现配置语法错误比只检查进程存在更实用。3.4 一键部署脚本 deploy.sh下面这段 bash 脚本是整个离线部署工具的入口覆盖了从校验、装二进制、加载镜像到启动服务的全流程#!/usr/bin/env bash set -euo pipefail BASE_DIR$(cd $(dirname $0) pwd) cd $BASE_DIR echo [1/5] 校验离线包完整性... sha256sum -c sha256sums.txt echo [2/5] 安装 docker-compose如已存在则跳过... if ! command -v docker-compose /dev/null 21; then install -m 755 bin/docker-compose-linux-aarch64 /usr/local/bin/docker-compose fi docker-compose version echo [3/5] 加载 tengine 镜像... if ! docker images --format {{.Repository}}:{{.Tag}} | grep -q tengine:3.1.0-arm64; then docker load -i images/tengine-arm64-3.1.0.tar fi echo [4/5] 校验运行架构... docker image inspect tengine:3.1.0-arm64 \ --format {{.Architecture}} | grep -q arm64 echo 架构校验通过 echo [5/5] 启动服务... docker-compose --env-file compose/.env \ -f compose/docker-compose.yml up -d sleep 3 docker-compose -f compose/docker-compose.yml ps逻辑说明脚本开头用set -euo pipefail让任何一步失败都立即终止不会出现“脚本跑了但服务没起”的半吊子状态。第 1 步的sha256sum -c会逐个比对打包时生成的校验值离线包传输过程中如果有二进制损坏这一步就报警而不是等到容器启动时才暴露。第 2 步的install命令加-m 755明确设置二进制可执行权限。第 3 步先查镜像是否已存在避免重复加载浪费时间。第 4 步用docker image inspect检查镜像架构元数据确保当前宿主机与镜像架构匹配。最后一步启动容器并输出状态。需要特别注意docker-compose的两种形态。如果你把 v2 二进制安装成了docker-compose上面的命令全部成立如果目标机装了新版 Docker 自带的docker compose插件则要把命令替换成docker compose。更稳妥的写法是在脚本里先判断一下if command -v docker-compose /dev/null 21; then DOCKER_COMPOSEdocker-compose else DOCKER_COMPOSEdocker compose fi然后全脚本用$DOCKER_COMPOSE代替直接调用 docker-compose。这样不管现场是哪种环境脚本都不会因为命令名称差异而中断。4. 离线部署常见问题与排查这几个坑绕开能省半天部署工具最容易翻车的地方往往不是命令本身而是环境差异和细节遗漏。以下是我在 ARM64 离线交付过程中遇到最多的几类问题每条按“现象 → 原因 → 解决”列出。4.1 容器启动报exec format error现象docker compose up -d执行成功但容器状态一直是Restarting看日志只有一行standard_init_linux.go:... exec format error。原因镜像平台与主机平台不一致。最常见的是打包机上拉到了 x86 的镜像或者 Docker 自动选择了 multi-arch 清单里的 amd64 条目。ARM64 主机直接执行 x86 的 ELF 文件内核无法识别才会报这个格式错误。解决不要只靠docker pull自动选架构。如果拉取的是官方多架构镜像使用docker pull --platform linux/arm64强制指定如果是自己构建的镜像在 Dockerfile 的FROM指令里写明确的arm64v8基础镜像。部署脚本里加入第 4 步的架构检查用docker image inspect拿到Architecture字段做断言。另外打包机如果用的是 x86 qemu 模拟 arm64构建的镜像务必在真正的 ARM64 机器上做一次冒烟测试再交付模拟器构建的产物偶尔会踩到指令集兼容性问题。4.2 镜像加载成功但服务响应极慢或启动崩溃现象镜像在 ARM64 机器上docker load成功容器能启动但 CPU 占用 100%服务响应时间奇长加压测试时频繁 502。原因镜像虽然标了 arm64但内部某个二进制是从 x86 迁移过来的或者你用的基础镜像里带了 QEMU 用户态模拟层。更隐蔽的情况是 Java 或 Node 这类带 JIT 的运行环境在模拟层下触发了编译器崩溃。解决这类问题几乎只能靠架构纯净的镜像解决。准备离线包时记录下打包机的 CPU 型号和操作系统交付时让现场工程师用lscpu核对架构。ldd $(which nginx)看动态库依赖确认没有 x86 的 .so 残留。简单直接的办法如果条件允许在目标机器上用docker run --rm -it your-image uname -m输出是aarch64才说明容器内架构正确。4.3 docker-compose 命令不存在或者版本是 v1现象执行docker-compose version报command not found或者解析 compose 文件时报yaml.parser.ParserError。原因目标机器没装 docker-compose或者系统自带的还是老版本 v1v1 对 compose 文件里的某些字段如healthcheck语法兼容不完整对version字段的校验也固执。解决离线包里的bin/docker-compose-linux-aarch64就是为这个准备的。部署脚本里用install命令把它安装到/usr/local/bin/并包一层 Docker 自带的 compose 判断。如果改造脚本会引入风险那就在安装后打印docker-compose version结果让现场人员一眼看到 v2 的版本号特征。注意要确认这个二进制来自官方 GitHub Releases 的linux-aarch64构建产物别把 x86_64 编译的文件拷过来否则又是一次 exec format error。4.4 tengine 启动后访问页面是 403现象容器起来了docker ps显示 UP但 curl 访问首页 403 Forbidden。原因挂载的html目录属主不对。nginx 的 worker 进程默认以nobody用户运行而宿主机挂载进去的数据目录属主是 root权限是 750nobody没有读取权限于是 403。另一个原因是挂载nginx.conf时权限过严容器内无法读取配置。解决挂载进容器的目录属主改为 755 或将其属主改为 101部分镜像内 nginx 用户的 UID。更通用的做法是在 Dockerfile 里明确指定USER及工作目录并让html、logs目录在宿主机上有宽松的读权限。排查时先用docker compose exec tengine ls -l /usr/local/tengine/html看容器视角下的权限再检查 Docker 守护进程的user namespace配置如果启用了 userns-remap宿主机的 UID 映射关系会和容器内不一致。4.5 compose 里配置了 80 端口启动时报address already in use现象docker compose up -d输出Error response from daemon: driver failed programming external connectivity on endpoint... bind: address already in use。原因宿主机的 80 端口被其他进程占用。常规服务器上httpd、nignx 这类 Web 服务会自动注册占用 80或者某个 tomcat 直接监听在 0.0.0.0:80。解决先ss -lntp | grep -E :80|:443看占用方是谁。如果占用者是系统自带服务停掉并禁用如果是另一个 nginx 实例建议改 compose 的端口映射比如8080:80避免生产环境上同时存在两套 Web 服务的冲突。如果现场要求必须保留旧的 nginx 转发流量那就需要继续留用旧进程做前端入口让 tengine 容器监听在高位端口上。5. 验证部署结果的三个技巧架构确认、配置热加载、健康检查做完离线部署不要急着交付花三分钟做三件事回报很值。第一确认运行环境架构。执行docker image inspect tengine:3.1.0-arm64 --format {{.Architecture}} {{.Os}}输出应该是arm64 linux。再看目标机的uname -m是否为aarch64。两者对不上后续的稳定性就是运气问题。第二验证 tengine 配置是否正确加载。通过 compose 进入容器执行docker compose exec tengine /usr/local/tengine/sbin/nginx -t它会输出syntax is ok和test is successful两个确认。如果后续要修改配置用docker compose exec tengine sbin/nginx -s reload做热加载不要重启容器否则短连接在建连瞬间会受影响。第三给最终的验证做一个快速探测curl -I http://127.0.0.1/ 2/dev/null | head -n 1 curl -s http://127.0.0.1/nginx_status || echo stub_status 未开启第一条命令确认 HTTP 200 响应第二条命令验证 stub_status 模块是否生效。这个健康检查点的输出会告诉你 tengine 的进程是否正常接收连接。我自己的习惯是在离线包制作完成后先在一台干净的 ARM64 虚拟机上完整跑一遍./deploy.sh然后把整个部署过程录下来一起交给现场工程师。这个习惯救了我好几次——因为离线包打包时和交付时的 docker 版本不同经常出现version语法或healthcheck兼容问题但提前跑过一遍全流程现场基本不会有意外。以后你接手这类 ARM64 离线部署也照这个顺序先确认架构再校验离线包然后启动最后验证。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →