麒麟V10+ARM64部署Harbor v2.4.0:五大坑与完整避坑指南

发布时间:2026/10/8 6:59:27
麒麟V10+ARM64部署Harbor v2.4.0:五大坑与完整避坑指南 简介基于麒麟V10与ARM64架构的Harbor v2.4.0离线部署包面向需要在内网或国产化服务器上搭建镜像仓库的运维与开发工程师重点解决ARM平台兼容性、离线安装以及与Docker Compose、Kubernetes集成等实际痛点。资源共8个文件以shell脚本、配置模板、离线镜像压缩包和许可文件为主覆盖安装初始化、服务参数配置、证书生成与镜像离线分发等完整环节整体约407MB解压后目录结构清晰便于按需取用。目前已有314人学习下载尤其适合刚接触Harbor或正在推进国产化环境改造的团队。下载后可参照离线安装包与配套脚本在麒麟V10上完成从环境准备、参数调整、TLS证书生成到Harbor服务启动的完整部署模板文件亦为后续调整存储、对接Kubernetes提供清晰参照能有效缩短镜像仓库落地周期。1. 麒麟V10ARM64 上部署 Harbor v2.4.0和 x86 服务器的差别到底在哪在一台 x86_64 的 Ubuntu 服务器上部署 Harbor v2.4.0下载离线包、改两行配置、跑 install.sh基本二十分钟收工。换成麒麟V10 ARM64 之后同样一套流程会先给你一个 prepare 执行失败然后是镜像标签不匹配、容器反复重启、docker push 时连接拒绝每一步都像在拆盲盒。差别不在于 Harbor 本身而在于这个国产 Linux 发行版的软件源、内核版本和周边工具链和 Harbor 官方发布包的默认假设并不一致。这篇笔记按我实际部署走过的路径把架构确认、离线包准备、harbor.yml 参数、HTTPS 证书、五个高发坑一次讲完适合要在国产化 ARM 服务器上搭内网镜像仓库的运维和开发也适合想把已有 x86 仓库迁到 ARM 平台的人先做一轮预期管理。2. 架构与依赖ARM64 的 Harbor 组件集和麒麟V10 环境检查2.1 用 uname 和 docker info 把架构坐实别信“看起来是 ARM”很多刚接触国产化机器的同事会直接看 CPU 型号发现是 Phytium 或者 Kunpeng 就默认“反正是 ARM”。但实际部署前必须确认两件事内核看到的 CPU 架构以及 userland 是不是 64 位。麒麟V10 也有 32 位 userland 的版本如果用户态跑在 armv7l 上Harbor 官方 aarch64 镜像一个都起不来。登录机器后先把这三条命令跑一遍uname -m cat /etc/os-release docker info | grep -Ei architecture|ostype|server versionuname -m输出aarch64才是 64 位 ARM如果输出armv7l说明当前内核跑在 32 位兼容模式Harbor 的 arm64 镜像无法直接运行。/etc/os-release能看到 Kylin 的版本号常见的是 V10 SP1、SP2 或 SP3。SP3 的软件源里 docker-ce 版本更新遇到的兼容问题相对少。docker info里Architecture一栏对应 Docker daemon 运行时的架构这决定了 Docker 会优先匹配哪个平台的镜像。注意一个细节即使 uname 返回 aarch64如果 Docker 是旧版 18.09 或 19.03拉取多架构镜像时不一定能正确识别 arm64 的 manifest。所以依赖检查要放到 Docker 版本确认之后不要先急着 tar 解包。麒麟V10 常见是基于 Ubuntu 的软件生态但也有 Kylin 自维护的 rpm 系版本。部署前先确认你手里是 deb 系还是 rpm 系后面所有安装源的写法、证书信任目录都会不一样。我遇到过最典型的情况是deb 系麒麟用/etc/pki/ca-trust也能工作但默认只有/etc/ssl/certs路径二者不能混着配。2.2 Harbor 2.4.0 的组件镜像与架构匹配逻辑Harbor v2.4.0 不是一个单体服务它是一组 docker-compose 编排的容器集合核心组件包括 nginx、harbor-portal、harbor-core、harbor-jobservice、harbor-registry就是 Docker Distribution、harbor-dbPostgreSQL、redis以及可选的 trivy、notary、chartmuseum。判断“这套组件能不能在 ARM64 上跑”不是看 Harbor 主程序支持不支持而是看每个镜像的基础层是否也有 arm64 版本。nginx、postgres、redis 这些上游都有官方 aarch64 构建harbor-core、harbor-jobservice、harbor-registry 这些 Go 和静态编译产物官方同样发布了 arm64 版本。所以只要拿到正确的镜像标签整个编排跑起来不存在架构层面的硬障碍。真正的翻车点通常在镜像导入环节。有人在 x86 机器上先docker save出 tar 包再传到麒麟 ARM 服务器上docker load然后 docker images 里确实能看到镜像但容器一起就报exec format error。这是因为 load 只是解包Docker 并不会在你 load 时提醒你这个镜像的 platform 与当前机器不符。建议导入后用下面命令检查每个关键镜像的架构字段docker image inspect goharbor/harbor-core:latest \ --format {{.Architecture}} {{.Os}}如果输出是amd64 linux说明当前这个 tag 指向的是 x86 镜像想要在麒麟V10ARM64 上跑要找到对应arm64的后缀标签重新打 tag或者从官方源直接拉 arm64 版本。还有一点容易被忽略镜像的Architecture和实际包含的二进制架构可能不一致稳妥的办法是直接把镜像跑起来验证而不是只看 inspect 输出。2.3 麒麟V10 上 Dockerd、compose 和 openssl 的版本边界Harbor v2.4.0 官方对 Docker 版本的要求并不激进但实际部署中我会至少用 Docker 20.10.x。太老的版本在拉取 multi-arch manifest 时选择不到 arm64 平台或者对 registry API 的兼容处理有问题表现为镜像能列出来但 push 时 400 错误。docker-compose 是另一个容易漏的依赖。Harbor 安装脚本在 v2.4 时代默认调docker-compose命令而麒麟V10 上不少环境只装了 Docker 自带的 compose v2 插件。先确认两个命令都在docker-compose version docker compose version如果只有docker compose而没有docker-compose可以做一个软链接指向 Compose v2 的二进制常见位置是/usr/libexec/docker/cli-plugins/docker-compose。软链接只是让旧脚本能找到命令不需要重装任何东西。openssl 的版本影响的是后面证书环节。麒麟V10 SP3 上 openssl 3.x 已经比较常见生成证书时默认签名算法如果太弱新版 Docker 客户端校验 HTTPS 证书时可能直接拒绝。后文第 4 章的所有 openssl 命令我都显式指定了-sha256这是避免踩坑的关键不要偷懒省略。3. 部署 Harbor v2.4.0 的手把手操作离线包、harbor.yml 与启动验证3.1 解压离线包并确认 prepare 工具架构Harbor 离线包解压之后里面的prepare是一个独立可执行文件负责根据 harbor.yml 生成 docker-compose 所需的配置。它本身是编译后的二进制有架构之分。这一步经常被忽略导致在 ARM 机器上./prepare直接报 Exec format error很多人误以为是 Harbor 不支持 ARM。先做一个快速检查mkdir -p /opt/harbor-install tar -xzf harbor-offline-installer-v2.4.0.tgz -C /opt/harbor-install cd /opt/harbor-install/harbor file preparefile输出里如果包含x86-64说明这个离线包里的 prepare 是为 x86 编译的不能直接在你当前机器上执行输出aarch64则可以继续走官方安装脚本。国内不少镜像源提供的离线包其实是 x86 的放到 ARM 上跑 install.sh 会因为 prepare 失败而中断。如果 prepare 是 x86 的不需要非得在 ARM 机器上重编译可以用官方 prepare 镜像以容器方式运行。先把离线包里的镜像全部导入docker load -i harbor.v2.4.0.tar.gz docker images | grep goharbor/prepare查看输出的标签如果只有 amd64 的 prepare 镜像要么从能访问的仓库拉取 arm64 版本的 prepare 镜像要么在有 arm64 支持的其他节点上导出镜像再导入。确认 arm64 的 prepare 镜像存在后重新打一个本地 tag避免 compose 配置里引用不到docker tag goharbor/prepare:v2.4.0-arm64 goharbor/prepare:v2.4.0然后再手动以容器方式执行 preparedocker run --rm \ -v $PWD:/harbor \ -v /var/run/docker.sock:/var/run/docker.sock \ goharbor/prepare:v2.4.0 prepare这段命令把当前 Harbor 目录挂载进容器同时挂载 docker.sock 让 prepare 能读取本地 Docker 环境信息。--rm表示执行完成后删除临时容器避免留下残留。如果你确认准备环境没问题也可以跳过容器方式直接./prepare走官方路径。3.2 harbor.yml 中必改的 5 个参数离线包解压后会有一个harbor.yml.tmpl模板先复制成正式配置再改cp harbor.yml.tmpl harbor.yml用 vim 打开后五个参数是每次部署必改的hostname: 192.168.10.20 http: port: 80 harbor_admin_password: Admin2024 data_volume: /data/harborhostname建议直接写成 Harbor 所在服务器的内网 IP而不是机器名。企业内部 DNS 记录未必可靠客户端 push 镜像时是拿这个 hostname 拼 registry 地址的写 IP 最直观也少一层 DNS 故障。http.port如果暂时不配 HTTPS这里保持 80后面第 4 章切 HTTPS 时再开 https 段。harbor_admin_password初始化管理员密码。Harbor 默认要求至少 8 位且包含大小写和数字弱密码会在安装阶段被直接拒绝。YAML 里如果密码包含#、等符号用单引号包住避免被解析成注释。data_volume所有镜像、数据库、证书都会落到这个目录。强烈建议放到独立数据分区不要放在根目录/下否则镜像体积增长后很容易把系统盘塞满。如果后面想启用漏洞扫描或 Chart 仓库需要在执行安装脚本时加--with-trivy或--with-chartmuseum。但在 ARM64 麒麟上我一般先不加特别是 trivy 首次漏洞库下载依赖外部网络内网环境很容易卡住。先把基础仓库跑通再加功能不迟。3.3 用 compose 拉起全部容器三种启动方式对比Harbor 启动容器有三种常见方式顺序上也对应不同的排查阶段第一种官方脚本方式./install.shinstall.sh 内部会自动调用 prepare然后执行 docker-compose up。前提是 prepare 可执行文件能在当前架构上运行。第二种容器 prepare 加 compose 方式适合 prepare 架构不匹配的场景。配置改完后docker run --rm \ -v $PWD:/harbor \ -v /var/run/docker.sock:/var/run/docker.sock \ goharbor/prepare:v2.4.0 prepare docker-compose up -d容器方式 prepare 生成的配置和官方脚本完全一致之后再用docker-compose up -d启动。第一次启动会创建 nginx、core、jobservice 等容器-d参数让它们在后台运行。第三种分步排查方式。如果前面两种起不来就手动拆开执行把输出全部打出来./prepare 21 | tee /tmp/harbor-prepare.log docker-compose config 21 | tee /tmp/harbor-compose-config.log docker-compose up -d 21 | tee /tmp/harbor-up.logdocker-compose config会验证生成的 compose 文件语法是否合法这步报错通常能直接定位到 harbor.yml 里的字段拼写错误。日志一定要留着后面排查容器反复重启时会用到。3.4 启动后的健康检查清单容器都起来之后不要急着去看网页。先跑一遍下面的检查docker-compose ps curl -k -I http://192.168.10.20/v2/ docker logs harbor-core --tail 200 21 | grep -i errordocker-compose ps应该看到 8 个左右容器处于 Up 状态端口映射与 harbor.yml 一致。curl /v2/是 Docker Registry API 的根路径返回 200 或 401 都说明 nginx 和 registry 通了返回 connection refused 则说明端口未监听或有防火墙。harbor-core的日志里如果连续出现 database 相关错误直接跳到第 5 章第 3 节排查。注意Harbor 的 Web 页面首次访问会加载不少静态资源如果看到页面出来了但接口 502大概率是 harbor-core 还在等数据库就绪等一两分钟再刷新即可。不要一看到 502 就立刻重启容器给它一个初始化时间。4. 给 Harbor v2.4.0 配自签名 HTTPS证书生成、签发与双向信任配置4.1 openssl 生成 CA 和服务端证书SAN 扩展不能省内网仓库用自签名证书很正常但很多人生成证书省了 SAN 扩展结果 Docker 客户端始终报 x509 校验失败。新版 Docker 和 Go 客户端在校验证书时只认subjectAltName不再自动把 CN 当成主机名。所以服务端证书里必须包含 Harbor 的 IP 或域名。下面是我在麒麟V10 上常用的一组生成命令mkdir -p /data/cert cd /data/cert # 生成 CA 私钥4096 位用于签发服务端证书 openssl genrsa -out ca.key 4096 # CA 自签名根证书有效期给 3650 天内网自用不用频繁续 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ -subj /CCN/STBeijing/LBeijing/ODemo/OUInfra/CNHarbor-CA \ -out ca.crt # 服务端私钥2048 位足够 openssl genrsa -out server.key 2048 # 生成证书请求CN 直接写 Harbor 的内网 IP openssl req -new -key server.key \ -subj /CCN/STBeijing/LBeijing/ODemo/OUInfra/CN192.168.10.20 \ -out server.csr # 用 SAN 扩展签发服务端证书IP 和 DNS 按实际 hostname 调整 openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -out server.crt -days 825 -sha256 \ -extfile (printf subjectAltNameIP:192.168.10.20,DNS:harbor.local)这段命令的核心是最后一个extfile参数它把 SAN 写进证书扩展。IP:192.168.10.20必须和你 harbor.yml 里的 hostname 保持一致如果 hostname 配的是域名这里就写DNS:域名。-days 825是故意选一个少于 825 天的有效期避免部分客户端对超长有效期证书的兼容问题。生成后用下面命令验证证书里的 SAN 是否真的写进去openssl x509 -in server.crt -noout -text | grep -A1 Subject Alternative Name输出里必须能看到IP Address:192.168.10.20。看不到就回到上一步重新签发这一步不通过后面 Docker 怎么配证书都没有用。4.2 改 harbor.yml 启用 https 并重建容器得到 server.crt 和 server.key 后回到 Harbor 目录修改 harbor.yml加入 https 段落hostname: 192.168.10.20 http: port: 80 https: port: 443 certificate: /data/cert/server.crt private_key: /data/cert/server.keycertificate和private_key写绝对路径。Harbor 的 prepare 会把这些路径映射到容器内部并挂载不需要把证书复制到 Harbor 目录里。接着重新执行 prepare 和容器重建。注意不是简单的 restart 就能生效因为 nginx 配置是在 prepare 阶段生成的docker-compose down ./prepare docker-compose up -ddown会停止并删除旧容器但不会删除数据卷镜像和数据库都还在。prepare 会重新生成 nginx 配置把 443 端口挂进去。如果 prepare 仍然有架构问题还是用第 3 章的容器方式执行。重启后检查端口监听ss -lntp | grep -E :80|:443正常应该看到 80 和 443 都有监听。此时浏览器访问https://192.168.10.20因为证书是自签的浏览器会提示风险直接点继续即可。4.3 让麒麟V10 和 Docker daemon 同时信任新 CA浏览器能访问只是第一步更关键的是让 Docker daemon 信任这个 CA否则 docker login 和 docker push 会一直报证书错误。麒麟V10 是基于 Debian/Ubuntu 生态的系统信任根证书用update-ca-trustcp /data/cert/ca.crt /etc/pki/ca-trust/source/anchors/harbor-ca.crt update-ca-trust extract有些最小化安装的麒麟V10 没有/etc/pki/ca-trust目录需要先创建。如果系统里是update-ca-certificates风格对应把证书放到/usr/local/share/ca-certificates/再执行 update-ca-certificates。两种方式效果一样只是路径不同。Docker daemon 的信任是单独管理的不能依赖系统证书库。要让 docker 客户端在访问192.168.10.20时信任 Harbor 的 CA需要把 CA 放到 Docker 的证书目录mkdir -p /etc/docker/certs.d/192.168.10.20 cp /data/cert/ca.crt /etc/docker/certs.d/192.168.10.20/ca.crt systemctl restart docker/etc/docker/certs.d/hostname/ca.crt是 Docker daemon 的固定校验路径目录名必须和 Harbor 的 hostname 完全一致。如果 hostname 是域名目录就要叫域名。一定要在重启 Docker 之后再做后续 login 和 push 测试证书是 daemon 启动时加载的不重启不会生效。配置完成后验证docker login 192.168.10.20 -u admin -p Admin2024如果 login 成功说明证书信任链和 Harbor 的 https 服务都正常。此时再看第五章第 1 条里那类推送失败通常就不会出现了。5. 麒麟V10 ARM64 部署 Harbor 的 5 个高发坑现象、原因与解决办法5.1 推送失败dial tcp 连接拒绝背后的协议与端口问题现象docker push 192.168.10.20/library/demo:v1报错日志里出现Get https://192.168.10.20/v2/: dial tcp 192.168.10.20:443: connect: connection refused。原因docker 客户端默认优先走 HTTPS而当前 Harbor 还只开了 HTTP 80 端口443 没有监听。还有另一种情况是网卡到 Harbor 之间被防火墙拦了但防火墙拦通常是 timeout 而不是 connection refused据此可以区分。解决先确认 Harbor 监听端口执行ss -lntp | grep -E :80|:443。如果只有 80说明协议没对上。在/etc/docker/daemon.json里给这个仓库配置 insecure-registries{ insecure-registries: [http://192.168.10.20:80] }注意这里写了完整的http://和端口明确告诉 Docker 用 HTTP。只写192.168.10.20在某些版本上仍然会先试 HTTPS。改完systemctl restart docker。如果已按第 4 章配好 HTTPS则不需要这个配置直接用证书信任即可。防火墙场景下麒麟V10 如果开了 firewalld开放端口firewall-cmd --permanent --add-port80/tcp --add-port443/tcp firewall-cmd --reload5.2 容器起不来或 exec format error架构错位的典型表现现象从离线 tar 包 load 镜像后执行 docker-compose up容器一直Restartingdocker logs 里反复出现exec format error。有些场景下如果在 qemu 或 boot 工具里检测镜像内核段还会看到类似bad linux arm64 image magic的提示本质上都是同一个问题目标二进制或镜像的平台不是 ARM64。原因离线包里的镜像是从 x86 机器打包的或者镜像 tag 选择的是 amd64 版本。Docker load 阶段不校验平台只有真正 exec 容器进程时才暴露。解决回到第 2.2 节逐个 inspect 关键镜像的 Architecture。如果确认是 amd64不要试图在 ARM 机器上“硬跑”老老实实拉 arm64 版本的镜像重新打 tag。对需要多架构发布的场景在构建阶段就用 buildx 同时出 amd64 和 arm64docker buildx build --platform linux/arm64 \ -t 192.168.10.20/library/app:v1 --push .这句话的意思是让 buildx 以 arm64 平台构建并直接推到 Harbor。用--push会先登录目标仓库否则需要先docker buildx build --load再手动 push。5.3 core 容器反复重启数据库就绪与数据盘性能现象Harbor 页面 502docker-compose ps里 harbor-core 显示 Restarting查看日志docker logs harbor-core --tail 100里面出现failed to ping database或dial tcp 127.0.0.1:5432 connect: connection refused。原因Harbor 容器编排里 postgres 与 core 几乎同时启动core 在数据库未就绪时连续重试失败。如果数据卷放在 NFS、CephFS 这类网络存储上postgres 初始化速度会明显变慢core 更容易判定启动失败。解决把 data_volume 放到本地物理盘或本地 RAID 上这是最根治的办法。如果数据目录必须放在共享存储至少给 core 容器加一个等待脚本或手动重启docker-compose restart harbor-core重启前先确认docker-compose ps里 harbor-db 已经是 Up 状态并且docker logs harbor-db里能看到database system is ready to accept connections。数据库没有 ready 就直接重启 core只会再翻车一次。5.4 重启后 Harbor 全没了systemd 与服务自启动现象麒麟V10 重启后docker ps 里一个 Harbor 容器都看不到80 和 443 端口无监听需要手动进目录执行 docker-compose up 才能恢复。原因Harbor 容器本身没有注册成 systemd 服务。docker daemon 开机启动了但 docker-compose 不会自动把容器拉起来。如果服务器意外断电即使容器有 restart 策略也可能因为 Docker 未启动而没机会恢复。解决把 Harbor 包装成 systemd 服务。创建/etc/systemd/system/harbor.service[Unit] DescriptionHarbor Container Service Requiresdocker.service Afterdocker.service [Service] Typeoneshot RemainAfterExityes WorkingDirectory/opt/harbor-install/harbor ExecStart/usr/bin/docker-compose up -d ExecStop/usr/bin/docker-compose down [Install] WantedBymulti-user.targetWorkingDirectory要改成你实际的 Harbor 目录。RemainAfterExityes表示 up 命令执行完就算服务成功不会因为命令退出而把服务标记为失败。这段 unit 的 ExecStart 里用了 docker-compose 的绝对路径避免 systemd 环境里 PATH 不完整导致找不到命令。启用并立即验证systemctl enable harbor.service systemctl daemon-reload systemctl restart harbor.service systemctl status harbor.service之后重启机器Harbor 会自动跟着 docker 一起起来。如果你不想写 systemd也可以把 docker-compose up 写到 rc.local但 systemd 的可观测性和排错体验好得多。5.5 日志和镜像占满磁盘Harbor 与 Docker 的磁盘清理现象某天 docker push 镜像时报no space left on deviceHarbor Web 页面也开始报 500。登录服务器一看df -h显示根分区或 /var/lib/docker 所在分区已满排队最多的往往不是镜像本身而是容器日志。原因Harbor 组件多nginx、core、jobservice 都会写日志默认不限制日志文件大小运行一两个月单容器日志可能到几十 GB。麒麟V10 系统自身的 journald 日志同样会占用 /var/log两者叠加很容易把系统盘塞满。解决先看占用cd /var/lib/docker/containers du -sh $(ls -t | head -20) | sort -h再对 Docker daemon 做全局日志上限。修改/etc/docker/daemon.json{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }max-size10m限制单个日志文件不超过 10MBmax-file3保留最多 3 个轮转文件。这是一个全局配置会对之后新建的所有容器生效旧的容器仍需要重建日志驱动才能应用所以改完后对 Harbor 执行一次docker-compose up -d重建即可。注意不要在生产数据没备份的情况下直接docker system prune -a --volumes那会把镜像缓存和历史容器全清掉虽然是回收空间最快的方法但“后悔药”是真的没有。6. 部署只是开始客户端推送配置与跨仓库镜像同步的两个落地技巧6.1 在客户端配置证书信任后推送镜像Harbor 部署完成后不能只在自己机器上访问还要让其他内网服务器能推拉镜像。把所有客户端的 Docker 证书配置统一比每个客户端都配 insecure-registries 更安全也不要混用。客户端机器上执行mkdir -p /etc/docker/certs.d/192.168.10.20 cp /data/cert/ca.crt /etc/docker/certs.d/192.168.10.20/ca.crt systemctl restart docker注意/data/cert/ca.crt是 Harbor 服务器的 CA 文件需要先拷贝到当前客户端。没有证书文件时可以用scp从 Harbor 服务器拉下来但传输过程中最好校验一下文件内容是否完整。客户端配置完成后的推送流程如下docker login 192.168.10.20 -u admin -p Admin2024 docker tag busybox:latest 192.168.10.20/library/busybox:v1 docker push 192.168.10.20/library/busybox:v1docker tag的格式是仓库地址/项目名/镜像名:标签项目名必须是 Harbor 里已经存在的项目否则 push 会被拒绝。默认有一个 library 项目也可以先在页面上建好项目再推。6.2 用 Harbor 复制任务在不同 ARM64 仓库间同步镜像如果在多个 ARM64 节点上还要各自部署一套 Harbor手动逐个推镜像太原始。Harbor 自带的复制功能可以直接做仓库间同步。在 Harbor 页面进入“系统管理”下的“仓库管理”新建一个远端目标填另一套 Harbor 的地址、协议和访问凭证。这个目标不需要对公网开放内网可达即可ARM64 仓库之间同步保持架构一致。随后在“复制管理”里新建规则关键参数是源资源过滤器、触发方式和覆盖策略。标签过滤写arm64或aarch64可以有效避免把 x86 镜像同步过来触发方式选“手动”先跑一遍试错确认无误后改成“定时”或“事件驱动”。我最开始的习惯是每次部署都手动 push后来发现一旦镜像数量上百漏 push 一个 tag 就会导致后续环境回滚困难。现在我会给每套 ARM64 仓库建一条复制规则把基础镜像从主仓库同步过去。希望这篇笔记能让你在麒麟V10 上部署 Harbor v2.4.0 时少走几趟弯路也少几个半夜被 push 失败叫醒的晚上。本文还有配套的精品资源点击获取