
简介面向ARM64架构服务器运维与开发人员该工具提供基于docker-compose的Tendis 2.7.0单机版一键离线部署方案解决内网环境缺少镜像、手工配置繁琐的痛点适合需要快速搭建兼容Redis协议的缓存存储服务的场景。压缩包共19个文件大小约310MB主要包含Dockerfile、docker-compose yaml模板、tendis配置模板、启停与检测shell脚本、离线镜像包以及redis-cli等辅助工具覆盖从环境准备到部署、启动、停止、卸载的完整操作链。目前已有283人学习下载可见关注度较高。借助该方案用户可自定义数据目录、端口和密码并实现配置文件与数据目录持久化避免容器重建导致数据丢失同时离线设计使无外网机房也能顺利安装部署。对需要标准化交付Tendis单机服务或简化运维流程的ARM64平台用户这是一份可直接落地的参考资源。1. ARM64离线部署tendis这份docker-compose一键包解决了什么拿到一台ARM64服务器没有外网apt源全部指向内网却要在上面跑tendis当Redis用——这套基于ARM64架构、借助docker-compose编排的tendis单机版离线部署工具就是把整件事从半天工作量压到几分钟的东西。它把一个centos8.3.2011的基础镜像、tendis 2.4.2的ARM64二进制、配置模板、镜像构建脚本和op.sh操作脚本全部装进一个tar.gz包解包后依次执行几条命令就能完成部署、启动、停止、卸载和检测。适合两类人一类是在内网环境里被依赖问题卡住的运维另一类是手里有一批ARM64板子、想快速验证tendis替代Redis场景的研发。下文我按拆包、镜像、配置、排坑、验证五个环节过一遍。2. 拆解离线包从tar.gz文件清单到docker-compose调用链2.1 解包后的真实结构拿到tendis-single-arm64-2.4.2.tar.gz先别急着docker load我习惯先解包看结构确认目录层级再动手避免后面挂载路径写错到处找文件mkdir -p ~/tendis-offline tar -xzf tendis-single-arm64-2.4.2.tar.gz -C ~/tendis-offline cd ~/tendis-offline find . -maxdepth 2 -type f | sort解包后你大概率会看到这样一批文件op.sh、build.sh、Dockerfile、centos8.3.2011.tar.gz、tendisplus.conf、tendis-arm64-2.4.2.tar.gz外加templates目录和pkgs、conf等子目录。这里有个容易看懵的点容器镜像的tar包和资原总包都是tar.gz区分方式是看文件名带不带arch和版本号。centos8.3.2011.tar.gz是基础系统镜像tendis-arm64-2.4.2.tar.gz是打好的tendis应用镜像后者通常放在images目录下。总包里同时出现Dockerfile和build.sh说明这个工具支持两种用法直接用现成镜像或者自己重新构建镜像。我一般先看images目录有没有成品有就跳过build。模板目录templates是整套配置的源头里面放着docker-compose-single-tpl.yaml、tendisplus-tpl.conf、single.conf.tpl三个模板文件。这三个文件是部署时真正被渲染的对象端口、密码、数据目录都在这一层替换后续第4章细讲。conf和nc这类辅助文件用于检测端口和下发配置属工具集自带的小件。2.2 每个文件分管的活文件/目录作用使用时机op.sh一键操作总入口封装deploy/start/stop/uninstall/check部署全流程build.sh基于Dockerfile构建tendis镜像无现成镜像时Dockerfile镜像构建定义固定基础镜像和二进制路径配合build.shcentos8.3.2011.tar.gzARM64基础系统镜像离线导入用deploy时被docker loadtendis-arm64-2.4.2.tar.gz打好的tendis应用镜像deploy时被docker loadtendisplus.conftendis服务端配置模板容器内生效templates/docker-compose-single-tpl.yamlcompose编排模板定义端口、挂载、环境变量deploy时渲染templates/tendisplus-tpl.conftendis配置的变量版deploy时sed替换templates/single.conf.tpl精简配置模板检查时用check时对比pkgs/辅助软件包如nc等check端口时这个表对应的是最常见的解包结果。不同批次打包可能在文件层级上有出入但不影响部署逻辑总包负责运输op.sh负责编排templates负责渲染两个tar.gz镜像负责提供运行环境。2.3 docker-compose模板怎么变成最终yaml部署时op.sh做的事情可以概括为三步先把两个tar.gz镜像load进docker再读取templates/docker-compose-single-tpl.yaml生成最终compose文件最后执行docker-compose up。模板渲染这步常见做法是直接用sed做变量替换不需要额外装工具sed -e s|TENDIS_PORT|6379|g \ -e s|TENDIS_PASSWORD|yourpass123|g \ -e s|DATA_DIR|/data/tendis|g \ templates/docker-compose-single-tpl.yaml docker-compose.yaml模板里的占位符被替换成实际值这一步决定最终落地的端口、密码和数据目录。用|做分隔符是为了避免密码里出现/导致sed转义地狱这是我在离线脚本里习惯性保留的写法。替换完建议先cat docker-compose.yaml人工过一遍确认占位符没有残留再up。3. 镜像与基础层centos8.3.2011.tar.gz和Dockerfile怎么拼3.1 为什么要自带基础镜像ARM64离线部署最大的坑不在tendis本身而在基础镜像。公网docker hub在部署环境通常不可达即便能拉也经常拉到手一个x86_64的镜像在ARM64机器上直接exec format error。这个包把centos8.3.2011的ARM64镜像单独打成tar.gz就是为了绕开这个链路。选centos8.3.2011而不是alpine我的理解是tendis的二进制依赖glibcCentOS系镜像里glibc版本和动态链接器路径最稳。tendis的RocksDB模块对不同系统的依赖很敏感alpine的musl libc大概率会出现运行时崩溃所以这种生产向的包基本不会用最小镜像赌运气。还有个细节这个基础镜像同时是构建镜像和运行镜像。build.sh里FROM的就是它构建时编译器用的头文件库和运行时依赖完全一致不会出现构建在一个系统、跑在另一个系统的兼容性问题。对离线环境来说少一个外部依赖就少一个故障点。3.2 Dockerfile与build.sh的配合Dockerfile的写法决定了镜像能不能跨机器复用。常见做法分四段FROM基础镜像、COPY二进制和配置、暴露端口、指定前台启动参数FROM centos:8.3.2011 MAINTAINER offline-deploy COPY tendisplus /usr/local/bin/tendisplus COPY tendisplus.conf /etc/tendis/tendisplus.conf RUN mkdir -p /data/tendis \ chmod x /usr/local/bin/tendisplus EXPOSE 6379 ENTRYPOINT [/usr/local/bin/tendisplus, /etc/tendis/tendisplus.conf]注意Dockerfile里COPY的是编译好的tendis二进制不是源码。这里有个很容易翻车的点tendisplus进程需要依赖RocksDB的动态库如果源码包里有配套的librocksdb.so也要一并COPY到/usr/local/lib并执行ldconfig否则容器起来秒退日志里全是error while loading shared libraries。build.sh只是把这层逻辑封装成一条命令#!/bin/bash docker build -t tendis-arm64:2.4.2 . docker save tendis-arm64:2.4.2 | gzip tendis-arm64-2.4.2.tar.gz构建完成后打成tar.gz方便拷贝到无网机器。注意build.sh里tag一定要带具体版本号不要用latest离线环境里镜像一旦多了latest指代不明非常难排查。3.3 离线load镜像的时机与tag规则拿到分发的tar.gz镜像后部署环境只需要做一件事docker load -i centos8.3.2011.tar.gz docker load -i tendis-arm64-2.4.2.tar.gzload完成后用docker images确认镜像名和tag。不同的打包方式镜像名可能不一样常见的是centos:8.3.2011和tendis-arm64:2.4.2。如果docker-compose模板里写的镜像名和load进本地的名字不一致Compose会尝试远程拉取离线环境直接失败。这个对不上往往是一开始没检查docker images造成的。我一般会在load后加一个强制tag的习惯docker tag tendis-arm64:2.4.2 tendis-arm64:2.4.2这条命令看着多余实际能保证后续部署用的镜像名和构建tag完全一致。如果分发包是从别的机器save出来的镜像名很可能带了源机器的仓库前缀这时候需要根据模板里的image:字段反推把名字纠正成模板期望值再部署。4. 配置模板与op.sh端口、密码、持久化是这么生效的4.1 tendisplus.conf模板里的变量位tendis的核心配置和Redis高度接近端口、绑定地址、requirepass、数据目录、日志路径。模板版的tendisplus.conf里不会直接写死值而是留占位符交给sed替换bind 0.0.0.0 port TENDIS_PORT requirepass TENDIS_PASSWORD dir TENDIS_DATA_DIR daemonize no save 900 1 save 300 10 logfile /data/tendis/tendis.logdaemonize no这条很关键。容器里跑的应用必须是前台进程如果拷贝配置时把默认值带成daemonize yes容器启动后tendis进程立刻退到后台主进程判定结束整个容器会反复重启。我见过好几个案例都是栽在这里现象是docker ps显示容器总是Restarting日志又看不到具体堆栈。dir决定RocksDB的数据落盘位置也是第4.3节持久化的根基。这个目录必须提前创建否则tendis启动时写不进去会直接abort。模板的价值在于整个配置文件的变动范围被缩小到几个变量位不需要懂tendis全量配置项改同事留下的脚本也不容易改崩。4.2 op.sh 的五条命令op.sh是整个工具的操作入口我解包后第一件事就是看它的用法./op.sh deploy ./op.sh start ./op.sh stop ./op.sh uninstall ./op.sh check内部实现一般是case分发每种子命令做一组有限操作#!/bin/bash case $1 in deploy) docker load -i centos8.3.2011.tar.gz docker load -i tendis-arm64-2.4.2.tar.gz sed s|TENDIS_PORT|${TENDIS_PORT:-6379}|g ... docker-compose.yaml docker-compose up -d ;; stop) docker-compose stop ;; uninstall) docker-compose down -v ;; check) docker-compose ps nc -zvv 127.0.0.1 ${TENDIS_PORT:-6379} ;; esac部署顺序是写死的先load镜像再渲染模板最后才up。如果模板里的镜像名和实际load镜像tag不一致这一层就会被卡住。op.sh命令底层操作注意点deployload镜像 sed渲染 compose up需先确认两个tar.gz存在startcompose start不重新创建容器stopcompose stop保留容器和数据uninstallcompose down -v-v连数据卷一起删慎用checkcompose ps nc探测端口不能验证密码stop和uninstall的边界要分清stop只是停容器数据还在uninstall带-v会把匿名数据卷一并清掉。如果数据目录是bind mount方式挂载-v不会删宿主机目录但如果你把数据放在容器卷里-v一执行数据就没了没有后悔药。4.3 数据目录与配置文件持久化的绑定逻辑tendis的RocksDB把数据写在dir指定目录下容器重启后目录清空就等于数据全没。所以compose模板里一定要做目录挂载services: tendis: image: tendis-arm64:2.4.2 container_name: tendis-single ports: - 6379:6379 environment: - TENDIS_PASSWORDyourpass123 volumes: - /data/tendis:/data/tendis - /etc/tendis/tendisplus.conf:/etc/tendis/tendisplus.conf:ro宿主机/data/tendis和容器内/data/tendis一一对应RocksDB的SST文件直接写到宿主机磁盘容器删除也不怕。配置文件用只读方式挂载防止容器内被意外改动这是运维上一个值得保留的习惯。这里有个参数细节如果宿主机目录没提前创建docker会自动建目录但属主是root。如果容器内tendis以非root用户运行就会变成目录在但写不了启动阶段报mkdir /data/tendis/tmp: permission denied。解决方法是部署前显式mkdir -p /data/tendis chown或者干脆让容器内以root跑离线内网环境通常不纠结这个。5. 避坑排查ARM64上部署tendis的五条实测记录5.1 容器起不来报exec format error现象docker-compose up后容器秒退docker logs看不到tendis日志docker inspect显示状态为exited错误信息里出现exec format error。原因镜像架构和宿主机CPU架构不匹配。最常见的是把x86_64的tendis镜像load到了ARM64机器上少数情况是在x86机器上用qemu模拟ARM64底层后误把模拟环境当成真机镜像架构看着是arm64实际执行链完全不对。解决先docker images看镜像架构是否带arm64标识再检查宿主机uname -m是否输出aarch64。如果确实架构不匹配只能重新分发arm64版本的tar.gz。如果你是在x86上跑qemu模拟ARM64做验证建议直接放弃这条路线RocksDB在这种模拟底下的IO行为失真验证结果没有参考价值不如找一台真机或云厂商的ARM64实例。5.2 版本号对不上工具叫2.7.0二进制是2.4.2现象压缩包文件名写的是tendis-single-arm64-2.4.2但工具命名线是2.7.0配置参考2.7.0文档填参数结果tendis启动报未知配置项。原因工具的版本和tendis内核版本是两条线。工具版本迭代到2.7.0但里面的tendis二进制实际是2.4.2配套的RocksDB是5.13.4。按新版本文档配置旧版本二进制配置项不认识是必然。解决一切参数以包内tendisplus.conf模板和README为准。别只看工具命名去网上搜配置拿到的文档版本未必和包内二进制匹配。检查方式也简单进容器跑/usr/local/bin/tendisplus --version实际输出是什么版本就按什么版本的文档来。5.3 想升级RocksDB结果进程直接崩现象为了所谓性能把RocksDB动态库换成了更新版本tendis启动后几秒内SIGSEGV日志里能翻到rocksdb相关的调用栈但没有明确报错。原因tendis 2.4.2编译时和rocksdb 5.13.4强绑定RocksDB的接口在版本间经常变动态库里符号对不上就直接崩。这个包里的二进制和数据库版本是配套打包的拆开任何一个都会踩到黑匣子问题。解决不要动RocksDB版本。如果非要升级得从源码重新编译整套tendis而不是只换动态库。这个包的设计就是让你拿现成二进制直接用性能调优的参数在tendisplus.conf里调不要动依赖层。5.4 密码设置了redis-cli免密还能连现象配置里写了requirepass容器也起来了但redis-cli不带密码能连上甚至能执行INFO。原因最常见的两种一是配置模板里的requirepass占位符没被sed替换实际落到容器内的配置还带着TENDIS_PASSWORD字符串等于没有密码二是配置目录挂载时把宿主机旧配置覆盖了容器内新配置改了半天容器内跑的还是老文件。解决部署后第一步进容器内确认实际配置docker exec tendis-single cat /etc/tendis/tendisplus.conf | grep requirepass。如果占位符没替换回到宿主机重新跑sed别手改容器内的文件容器重建就丢。如果挂载覆盖了检查docker-compose.yaml里volumes字段的源文件路径确保指向渲染后的文件。5.5 卸载后重部署端口被占或数据残留现象执行uninstall后隔几天重新deploycompose报端口已被占用或者新的tendis实例起来后读到了旧数据排查半天。原因uninstall的docker-compose down只停容器和网络不会清理宿主机上通过bind mount挂载的数据目录。端口被占多数是旧容器没完全退出或者别的进程占用了6379。解决重新部署前按顺序做三件事docker ps -a看有没有同名容器残留ss -lntp | grep 6379看端口占用ls /data/tendis看数据目录里有没有老文件。确认不需要旧数据后手动清理再deploy。这个顺序我建议每次都走一遍成本不到一分钟能避免非常多的玄学问题。6. 部署完怎么验证从容器状态到数据写读一条龙6.1 先看容器状态和日志![未使用图片占位如无必要不插入]部署完成后先跑docker-compose ps确认状态是Up且没有频频重启。随后看日志重点不是看有没有输出而是看有没有反复刷新的异常堆栈docker-compose ps docker logs --tail 100 tendis-single注意检查日志里是否出现signal字样的崩溃记录。tendis的启动日志通常很短几行输出后就进入前台运行如果日志停在初始化阶段且无后续优先怀疑目录权限问题而不是怀疑二进制有问题。6.2 验证端口和密码nc -zv 127.0.0.1 6379 redis-cli -h 127.0.0.1 -p 6379 -a yourpass123 PING第一条验证端口通不通第二条验证密码对不对。如果nc通了但redis-cli报NOAUTH Authentication required说明密码生效了只是没带对属于正常防御。能PING通并返回PONG再执行一个SET/GET组合确认写入链路没问题。6.3 我的落盘检查习惯最后一步我会直接翻数据目录确认RocksDB真的往宿主机写了文件ls -l /data/tendis find /data/tendis -name *.sst | head -5看到.sst文件落在宿主机目录里说明持久化挂载是通的容器删了也不慌。在那以后我每次deploy完都强制走一遍这个流程先ps后logs再nc再redis-cli最后翻落盘目录全过一遍才敢把手里的离线包标记为可用。希望帮到你。本文还有配套的精品资源点击获取