ARM架构银河麒麟V10离线部署Docker与Nacos全攻略
2026/9/16 21:22:34 网站建设 项目流程

前阵子给客户做项目交付,对方丢给我一台ARM架构的银河麒麟V10服务器,环境属于业务内网,物理隔离,没有外网权限。需求一句话:在这台机器上先把Docker装好,再把Nacos注册中心跑起来,后面微服务联调要用。我原以为这是普通运维活,真正做起来才发现,离线安装最让人头疼的不是命令不会敲,而是你根本不知道系统还缺哪些底层依赖,该去哪里找合适架构的包。这篇文章把我这次部署的完整过程记录下来,从环境确认、安装包收集、本地yum源搭建、Nacos接入MySQL,到最后各种诡异坑的排查,一次讲清楚。做内网部署、离线交付的兄弟可以参考,能少走不少弯路。

1. 先把环境摸清楚:确认ARM麒麟版本和依赖闭环

1.1 上机第一步,别急着跑安装命令

很多人习惯拿到服务器就开搞,结果装到一半才发现系统版本不对、架构不对,白白浪费时间。我在动手前先把三样东西打出来:

cat /etc/os-release cat /etc/kylin-release uname -m

这次碰到的机器,/etc/os-release里显示是Kylin Linux Advanced Server V10,uname -m返回aarch64,是ARM64架构没跑了。麒麟V10这玩意有很多马甲,有基于CentOS的构建,也有基于openEuler的构建,还有SP1、SP2、SP3的区别。不同小版本的底层glibc版本、libseccomp版本、甚至systemd版本都不一样,这直接影响后面的RPM依赖解析。

所以第一件事永远是确认两个东西:架构是x86_64还是aarch64,系统是基于哪个发行版构建的。如果连这个都没搞清楚,后面下载的安装包大概率白下载。

1.2 版本选型:为什么我建议这套组合

离线环境不像线上可以随手yum update,装错了版本再修正的成本非常高。因此组件版本我一般选“稳”而不是选“新”。

组件推荐版本选择理由
Docker Engine24.0.x支持aarch64比较成熟,containerd、runc版本匹配稳定
Nacos2.3.x2.x后支持gRPC,配置管理、服务发现都稳定,ARM下跑Java无压力
JDKOpenJDK 8u或11Nacos 2.3.x对JDK 8兼容,运维习惯也最熟悉
MySQL/MariaDB8.0或系统自带MariaDB 10.x单机Nacos配置存储够用,ARM下也有官方二进制

我这次用的是Nacos 2.3.2。为什么不推荐最新的2.4.x/3.x?一方面是我对2.3.x的配置项更熟,摸得最透;另一方面,在离线环境里你没法指望临时查文档,用自己最有把握的版本,比追求“最新版”重要得多。

1.3 离线安装的依赖闭环思维

在线环境安装Docker,一条yum install docker-ce就完事,系统自动帮你把iptableslibseccompcontainerd.io这些依赖全部拉齐。但离线环境不一样,装Docker不只是装那一个RPM,它背后是一整棵依赖树。

我这次选择的方式是在在线机器上用repotrack把Docker及其所有依赖RPM完整地拉下来,然后上传到麒麟服务器,在服务器本地用这些RPM做一个本地yum源,最后还是通过yum命令来安装。这样做的最大好处是:依赖关系跟在线环境几乎一致,不会出现手动rpm -ivh时依赖缺失或顺序错乱的问题

2. 在能上网的机器上把安装包一次性备齐

2.1 用repotrack拉Docker全家桶

我先准备了一台能上网、架构同样是aarch64的CentOS 8/RHEL 8虚拟机,没有的话,直接在麒麟上把ARM开源镜像源的在线VM配好也行。然后在这台机器上下载软件包。

先把docker-ce的源配好。国内环境我习惯用阿里云镜像:

yum install -y yum-utils yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

然后创建一个目录,用repotrack把依赖完整拉下来:

mkdir -p /data/kylin-offline/rpms cd /data/kylin-offline/rpms repotrack docker-ce docker-ce-cli containerd.io docker-compose-plugin

这里核心参数是repotrack而不是yumdownloaderyumdownloader --resolve虽然也能拉依赖,但只会拉“当前yum环境下需要的那一层依赖”,对缺少系统基础包的情况支持得不够完整。repotrack会把所有被依赖的包全部拉下来,不管是不是已安装,用起来更省心。

拉完之后检查一下包架构:

find /data/kylin-offline/rpms -name "*.rpm" | xargs -I{} rpm -qp --qf '%{ARCH} {}\n' {} | sort | uniq -c

正常应该能直接看到大量aarch64包。如果混入了x86_64包,说明在线机架构或者yum源配置有问题,这时候就要停下来排查,别直接上传。

另外,记得把createrepo_c这个工具也拉下来。虽然平时毫不起眼,但到了离线服务器上你才会发现,本地yum源能不能建起来就靠它:

repotrack createrepo_c

2.2 备用方案:直接下Docker静态二进制包

如果你不想折腾RPM依赖,还有一个更“轻”的办法:Docker官方为Linux提供静态二进制归档包。下载下来解压,把里面几个二进制放到/usr/bin就能用。

curl -fsSL https://download.docker.com/linux/static/stable/aarch64/docker-24.0.9.tgz -o docker.tgz tar -xzf docker.tgz cp docker/* /usr/bin/

但静态包只是“能用”,不会帮你生成systemd服务、不会帮你创建docker用户组、也不会自动处理containerddockerd之间的协作关系。我建议只是把它当作应急方案。RPM源方式是更可控、更规范的做法,而且和yum的依赖管理能完美结合。

2.3 下载Nacos和JDK

Nacos本身是Java程序,不依赖特定CPU指令集,只要有对应的JDK就能跑。我用的是官方release里的包:

wget https://github.com/alibaba/nacos/releases/download/2.3.2/nacos-server-2.3.2.tar.gz

如果服务器yum源或麒麟系统里已经有OpenJDK,可以直接用系统的,不需要额外下载。没有的话,建议把OpenJDK 8的RPM也拉到同一目录。JDK 8在ARM上跑Nacos完全没问题,这也是Nacos自己官方文档里推荐过的组合。

把这些包从在线机拷贝到离线服务器的方式我就不啰嗦了,U盘、堡垒机、内网FTP都行。拷贝后务必做校验:

md5sum docker-*.rpm nacos-server-2.3.2.tar.gz > checksum.txt

2.4 顺便把MySQL/MariaDB准备掉

如果Nacos要用MySQL存储配置和服务数据,需要准备好MySQL或MariaDB。我这次直接用的系统自带的MariaDB,离线环境下安装最省事:

yum install -y mariadb-server systemctl enable --now mariadb

如果你需要走MySQL官方8.0,务必下载linux-glibc2.17-aarch64的二进制包,别拿到x86版。

3. 在离线服务器上搭本地yum源,把Docker装上

3.1 搭建本地仓库

把所有RPM上传到服务器的/data/kylin-offline/rpms目录后,先装createrepo_c

cd /data/kylin-offline/rpms rpm -ivh createrepo_c-*.rpm

然后创建仓库元数据:

createrepo /data/kylin-offline/rpms

这一步执行完会生成repodata目录。把仓库写进yum源:

cat > /etc/yum.repos.d/docker-local.repo <<'EOF' [local-docker] name=Local Docker RPM Repository baseurl=file:///data/kylin-offline/rpms enabled=1 gpgcheck=0 EOF yum clean all && yum makecache

3.2 正式安装Docker

本地源生效后,安装命令跟在在线环境几乎一样:

yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

装好之后先不急着启动,我先调整了/etc/docker/daemon.json

{ "data-root": "/data/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }

这里有两个细节解释一下:

  • >systemctl daemon-reload systemctl start docker systemctl enable docker systemctl status docker

    验证一下Docker是否正常工作:

    docker info docker run --rm hello-world

    如果离线环境连不上镜像仓库,hello-world会拉取失败,这是正常的,不代表Docker引擎有问题。

    3.3 本地装好后先验证镜像导入

    离线环境下没法现场拉镜像,所以预先在有网络环境的机器上准备好常用基础镜像,比如openjdk:8-jdk-alpinebusybox之类的。导出用的是docker save

    docker save openjdk:8-jdk-alpine busybox:stable -o /data/kylin-offline/images/base-images.tar

    后面在离线服务器上导入:

    docker load -i /data/kylin-offline/images/base-images.tar docker images

    这一步能确确实实证明Docker引擎工作正常。

    4. Nacos单机部署与外部MySQL接入

    4.1 解压并准备Nacos运行目录

    Nacos我放在/data/app下:

    mkdir -p /data/app tar -xzf /data/kylin-offline/nacos-server-2.3.2.tar.gz -C /data/app mv /data/app/nacos /data/app/nacos-2.3.2 ln -s /data/app/nacos-2.3.2 /data/app/nacos

    建一个软链,方便以后升级版本时切换目录,也方便写脚本时路径固定。

    启动前先确认java可用:

    java -version

    如果输出openjdk version "1.8.0_xxx",说明系统有JDK8。没有的话把之前下载的JDK RPM装上:

    yum install -y java-1.8.0-openjdk-headless

    4.2 初始化MySQL数据库

    Nacos的配置内容、服务注册信息都要落到数据库,所以先把库和账号建好:

    mysql -uroot -p
    CREATE DATABASE nacos_config DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER 'nacos'@'%' IDENTIFIED BY 'nacos@2024'; GRANT ALL PRIVILEGES ON nacos_config.* TO 'nacos'@'%'; FLUSH PRIVILEGES; USE nacos_config; SOURCE /data/app/nacos/conf/mysql-schema.sql;

    这里有个容易踩的坑:Nacos 2.3.x安装包里初始化SQL脚本可能叫mysql-schema.sql,而不是老版本的nacos-mysql.sql,目录里也可能同时存在多个脚本。执行之前先ls /data/app/nacos/conf/看清楚文件名,别按老经验一顿操作。

    另外,如果用的是MySQL 8.x,Nacos的连接用户最好用mysql_native_password。实测中有些老版本Nacos连MySQL 8的默认caching_sha2_password加密插件会报认证失败,干脆手动改一下:

    ALTER USER 'nacos'@'%' IDENTIFIED WITH mysql_native_password BY 'nacos@2024';

    4.3 修改application.properties

    编辑/data/app/nacos/conf/application.properties,把默认的derby数据源切到MySQL:

    spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai db.user=nacos db.password=nacos@2024

    如果你是先给服务注册中心用,暂时不接配置中心,也可以继续用内置Derby,少牵扯一个数据库组件。但只要Nacos要支撑多个服务的注册和配置发布,就趁早上MySQL,否则后面数据迁移会让你很头疼。

    4.4 启动Nacos并调整JVM参数

    Nacos默认启动脚本里的JVM参数偏向大内存机器,一些内网服务器内存只有8G甚至4G,直接启动很容易把可用内存吃满。我先调整环境变量再启动:

    export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk export JVM_XMS=512m export JVM_XMX=512m export JVM_XMN=256m sh /data/app/nacos/bin/startup.sh -m standalone

    Nacos 2.x的startup.sh支持JVM_XMSJVM_XMXJVM_XMN这几个环境变量,不用动脚本内容,比较干净。

    启动后看日志确认:

    tail -f /data/app/nacos/logs/start.out

    看到"Started Nacos"基本就成了。再检查8848和9848端口:

    ss -lntp | grep -E '8848|9848|9849'
    • 8848:HTTP主端口,控制台和客户端HTTP请求用;
    • 9848:gRPC服务端口,2.x客户端必须能访问,别忘了开防火墙;
    • 9849:gRPC服务端端口,后面的集群会用到。

    4.5 验证控制台和客户端注册

    浏览器直接访问http://服务器IP:8848/nacos,默认账号密码是nacos/nacos,进去后看一眼“服务列表”“配置管理”是否正常。第一次登录建议马上改密码,生产环境还要开启鉴权。

    再验证一个真实应用注册。随便用一个支持Nacos Discovery的微服务,或者用curl模拟Nacos注册:

    curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=test-demo&ip=192.168.1.20&port=8080'

    然后在控制台“服务列表”里能看到test-demo,就说明服务注册链路已经完全通畅。

    5. 可选操作:把Nacos放进容器跑起来

    有些场景下你希望Nacos也容器化,跟其他微服务统一用Docker管理。这一步我把离线镜像的方案也写出来。

    5.1 在线导镜像

    在能上网的aarch64机器上:

    docker pull nacos/nacos-server:v2.3.2 docker save nacos/nacos-server:v2.3.2 -o /data/kylin-offline/nacos-server-v2.3.2.tar

    这里务必确认在线机是ARM架构。如果你在x86机器上docker pull,拉下来的是amd64镜像,传到ARM服务器上用docker load虽然能导入,但docker run会直接报exec format error

    5.2 离线导入并运行

    docker load -i /data/kylin-offline/nacos-server-v2.3.2.tar docker images | grep nacos

    启动容器前,我建议先不要用默认的derby模式跑,还是连外部MySQL:

    docker run -d --name nacos \ --restart=always \ -e MODE=standalone \ -e SPRING_DATASOURCE_PLATFORM=mysql \ -e MYSQL_SERVICE_HOST=192.168.1.30 \ -e MYSQL_SERVICE_PORT=3306 \ -e MYSQL_SERVICE_USER=nacos \ -e MYSQL_SERVICE_PASSWORD=nacos@2024 \ -e MYSQL_SERVICE_DB_NAME=nacos_config \ -p 8848:8848 -p 9848:9848 -p 9849:9849 \ nacos/nacos-server:v2.3.2

    有一个最常见的坑必须说:MYSQL_SERVICE_HOST不要填127.0.0.1,因为容器里的127.0.0.1指向容器自己,不是宿主机。如果你非要填本机,要么用--network host模式启动Nacos容器,要么填宿主机在局域网内的真实IP。

    启动后观察日志:

    docker logs -f --tail 200 nacos

    容器方式部署Nacos时,如果要用到宿主机网络,也可以直接:

    docker run -d --name nacos \ --network host \ -e MODE=standalone \ -e MYSQL_SERVICE_HOST=127.0.0.1 \ ...

    --network host模式下端口映射参数不需要加,容器直接占用宿主机8848/9848端口,日志里看到的注册IP也更干净。

    5.3 本地目录挂载与备份

    容器作为无状态运行很爽,但Nacos的数据和配置一旦没了会很麻烦。给容器挂载两个目录比较稳妥:

    docker run -d --name nacos \ --restart=always \ -v /data/nacos/logs:/home/nacos/logs \ -v /data/nacos/conf:/home/nacos/conf \ ...

    这样日志和配置都落在宿主机,改配置不用进容器折腾,备份也简单。不过要注意,官方镜像里conf目录有初始化脚本,你做目录挂载时第一次启动前要保证宿主机目录里已经放好了application.propertiesmysql-schema.sql,否则容器会拿不到默认配置。

    6. 离线环境里那些防不胜防的坑

    6.1 Docker daemon启动失败,报overlay2不支持

    常见错误类似:

    failed to start daemon: error initializing graphdriver: driver not supported

    大概率是内核模块没加载,或者文件系统不支持overlay2。先看文件系统:

    df -T /data/docker

    确认是ext4xfs,再看xfs是否开启了ftype=1。ARM板子上如果用的是外部数据盘,格式化的时候没有指定-n ftype=1,overlay2就会拒绝工作。解决方法要么重新格式化数据盘并指定d_type,要么把>Error starting daemon: Error initializing network controller: Error creating default "bridge" network: iptables failed

    离线环境经常出现系统里连iptables都没装全。装上:

    yum install -y iptables ip6tables nftables

    装完后建议重启一次系统,再启动docker。因为iptables和nftables的内核模块在运行中加载不完整,重启后让systemd把服务拉起来,能省掉很多莫名其妙的网络问题。

    6.3 Nacos服务注册IP变成容器IP或veth绑定的IP

    很多应用在Kubernetes或者Docker里注册到Nacos的地址是内网虚拟IP,导致其他服务调不通。这个问题我直接在Nacos启动参数里指定IP:

    export JVM_FLAGS="-Dnacos.inetutils.ip=192.168.1.100" sh /data/app/nacos/bin/startup.sh -m standalone

    或者修改conf/application.properties

    nacos.inetutils.ip-whitelist=192.168.1.100

    这样报给客户端的地址就是你希望暴露的地址。服务注册IP被抢成容器IP,是Nacos容器化部署最常见的故障,尤其是多个网卡或多网段环境。

    6.4 Nacos跑了两天,控制台登录报502

    Nacos本身是Java进程,CPU和内存一吃紧,响应就会很慢,网关直接判定服务不可用。我遇到过不止一次,基本是JVM参数没调好,或者磁盘IO太差。建议:

    • 至少给Nacos 1G堆内存,8G内存的服务器别抠抠搜搜只给256M;
    • start.out日志如果刷得太快,把日志级别调成WARN;
    • dmesg -T | tail看一眼有没有OOM Kill,如果有,说明要么加内存,要么调小堆。

    6.5 重启后Nacos没起来

    Nacos的startup.sh不会自己注册成系统服务,所以重启后经常忘了启动。建议写一个systemd服务文件:

    [Unit] Description=Nacos Server After=network.target mariadb.service [Service] Type=forking Environment=JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk ExecStart=/data/app/nacos/bin/startup.sh -m standalone ExecStop=/data/app/nacos/bin/shutdown.sh Restart=on-failure User=nacos Group=nacos [Install] WantedBy=multi-user.target

    然后:

    systemctl daemon-reload systemctl enable nacos

    我这里用了nacos用户来跑,安全一点。如果直接root跑,把UserGroup两行删掉就行。

    6.6 客户端连不上9848

    Nacos 2.x的客户端和服务端之间走gRPC,端口是8848+1000=9848。很多人在控制台能看到服务,但客户端启动时报connection refused,一查就是防火墙只开了8848。记得把9848甚至9849都放通:

    firewall-cmd --permanent --add-port=8848/tcp firewall-cmd --permanent --add-port=9848/tcp firewall-cmd --reload

    麒麟系统如果用的是firewalld,就这样开;如果是ufw,语法不一样,但道理一样。

    再说一点个人经验。整套环境在离线状态做完后,我会把所有安装包、初始化脚本、配置文件汇总成一个目录,并在目录里写一份简单的README,记录系统版本、安装命令、改动过的配置项和踩坑记录。看似多花了二十分钟,但下一次交付新机器,或者出问题需要回滚时,这份记录真能救命。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询