简介面向在国产化机房或内网环境部署容器镜像仓库的运维、研发人员这份资源围绕麒麟V10和ARM64架构提供Harbor v2.4.0的离线部署工具集合针对无法直接拉取镜像的离线场景整合了aarch64适配的Harbor离线安装包、环境依赖准备脚本、服务编排配置模板以及证书生成脚本可配合Docker与Docker Compose使用并为后续对接Kubernetes集群提供基础镜像仓库支撑。 资源共8个文件以sh脚本、tar.gz离线包、yml配置文件为主另有license授权文本、prepare准备文件及tmpl配置模板其中sh脚本覆盖环境检查、证书生成与安装入口gz离线包内置Harbor所需镜像与依赖组件yml及tmpl用于定义仓库、数据库、Redis等服务的编排参数整体压缩包约407.22MB目录结构紧凑按脚本调用顺序可逐步完成部署。 已有314人学习下载适合需要在麒麟平台快速搭建Harbor的实践者借助这些脚本与模板可省去手动下载软件包、适配ARM64镜像和编写配置文件的繁琐步骤减少因官方x86版本不兼容带来的排错成本也能帮助理解Harbor在国产化环境中的部署要点与定制方法。1. 麒麟V10 ARM64 部署 Harbor v2.4.0这份离线包能解决什么拿到一台 ARM64 架构的麒麟 V10 服务器第一步往往不是装软件而是先确认手里的安装包架构对不对。harbor-offline-installer-v2.4.0-aarch64.tgz 就是为这类机器准备的离线部署包把 Harbor v2.4.0 镜像仓库工具完整搬到国产化内网环境不需要外网拉镜像也不需要额外的构建机。它解决的问题很具体——无外网条件下给 k8s 集群提供一个可登录、可推拉、带项目隔离的私有镜像仓库。适合正在做信创适配的运维和开发手里有鲲鹏、飞腾或其他 ARM64 服务器又不想被 docker hub 的拉取速度和外网限制卡住。这个包我拆过不止一次下面把环境准备、配置参数和踩过的坑都过一遍照着复现基本能一次落地。2. 环境准备麒麟V10 无网环境下 Docker 与 Compose 的补齐顺序2.1 为什么必须用离线包ARM64 与 x86 的镜像差异Harbor 在线安装器会在安装过程中从网络拉取多个组件镜像而麒麟 V10 这类内网服务器根本没有外网通道在线方式必然卡死。离线包把所有组件镜像打成一个 harbor.v2.4.0.tar.gzinstall.sh 直接导入本地镜像这才是内网里的可行路径也是我推荐直接选 aarch64 离线包而不是在线包的根本原因。另一个关键点是架构。ARM64 和 x86_64 是完全不同的 CPU 指令集镜像里打包的是编译好的二进制不能跨架构运行。如果误把 x86 的 Harbor 离线包拿到鲲鹏或飞腾机器上install.sh 流程能跑docker run 启动容器时大概率报 exec format error这是最典型的翻车现场。所以下载离线包时文件名里带 aarch64 才对得上 ARM64 架构x86_64 的机器则要换另一套包。我一般先跑三条命令确认环境再动手免得到最后一步才发现架构对不上uname -m docker version --format {{.Server.Arch}} file harbor-offline-installer-v2.4.0-aarch64.tgzuname -m 输出 aarch64 就说明是 ARM64 架构docker version 里的 Server.Arch 也要对应。file 确认压缩包本身是 gzip 数据而不是损坏文件。三个都对上了再进下一步能少走很多弯路。2.2 麒麟V10 无网安装 Docker离线 rpm 与 daemon 配置麒麟 V10 的包管理是 yum 系如果你手里没有内网 yum 源最常见的做法是找一台同样架构、同样系统的联网机器把 docker-ce 相关 rpm 一次性下载下来打包传到内网安装。我用的方式是这样# 在能联网的同架构机器上执行 yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo mkdir -p /tmp/docker-rpm yumdownloader --destdir/tmp/docker-rpm \ docker-ce docker-ce-cli containerd.io docker-compose-plugin tar czf docker-rpm-aarch64.tar.gz -C /tmp docker-rpm第一段给本机添加 docker-ce 的 yum 源第二段用 yumdownloader 只下载 rpm 包而不安装避免在联网机器上把环境改掉。注意 containerd.io 一定要带上docker 现在的容器运行时依赖它docker-compose-plugin 是给 docker compose v2 插件用的如果你后面用独立 docker-compose 二进制这个可以不要。把 tar 包传到麒麟 V10 内网机器后tar xzf docker-rpm-aarch64.tar.gz -C /tmp cd /tmp/docker-rpm rpm -ivh *.rpm --nodeps systemctl enable --now docker docker --versionrpm 直接装依赖优先用--nodeps兜底但这只是应急。更稳的做法是在内网建一个本地 yum 源用 createrepo 生成元数据再 yum install docker-ce让 yum 自己处理依赖。装完马上写 daemon.json我的习惯是把它拆开放在独立数据盘上cat /etc/docker/daemon.json EOF { data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, live-restore: true } EOF systemctl restart docker># 内网机器上确认 docker-compose --version uname -a sysctl net.ipv4.ip_forwarddocker-compose 版本建议不低于 1.29.x太老的直接替换成从同架构机器下载的 docker-compose-linux-aarch64 文件chmod x 后放到 /usr/local/bin/docker-compose 即可。uname -a 确认内核是 4.19 系列这是麒麟 V10 的典型内核版本。net.ipv4.ip_forward 必须是 1否则 Harbor 内部网络和外部端口映射会不通echo net.ipv4.ip_forward1 /etc/sysctl.conf sysctl -p这三个确认做完环境才算立住了。还有一个隐形坑麒麟 V10 默认开着 firewalld网页登录不上、docker login 超时先别怀疑 Harbor 配置用firewall-cmd --list-port看端口放行没有。我一般是临时放行 http/https 端口测试完再加永久规则。很多安装失败其实是环境变量没到位和 Harbor 自身没有关系先排查这一层能省掉一大半调试时间。3. 配置 harbor.ymlhostname、数据目录与 HTTPS 的落点3.1 离线包里哪些文件要动解压后包内文件大致如下我拆出来讲一遍哪些能碰、哪些不要碰文件作用我的处理方式install.sh安装入口导入镜像并拉起全部容器不动prepare根据 harbor.yml 生成 docker-compose.yml 和 nginx 配置不动common.sh安装脚本公共函数库不动cert.sh生成自签证书的辅助脚本需要时执行harbor.yml.tmpl配置模板含所有默认值复制后改名不直接改harbor.v2.4.0.tar.gz所有 Harbor 组件的镜像打包不手动处理LICENSE版权文件不动harbor.yml 是从 harbor.yml.tmpl 复制出来的它才是真正要编辑的文件。注意不要直接改 tmplprepare 在读取配置时会同时参考模板里的结构和 harbor.yml 里的值模板一旦改坏后面所有配置生成都会出错。install.sh 和 prepare 这两个脚本的逻辑是先跑 prepare 生成编排文件再跑 install.sh 导入镜像并启动。顺序反了配置会不生效。3.2 harbor.yml 关键参数hostname、端口、数据目录与证书一份能用的 harbor.yml 大概长这样。第一次部署我的建议是先跑 http把链路打通后再切 https所以下面的示例把 https 段注释掉了hostname: reg.k8s.local http: port: 8080 # https: # port: 443 # certificate: /data/cert/reg.k8s.local.crt # private_key: /data/cert/reg.k8s.local.key harbor_admin_password: YourStrongPass2024 database: password: YourDbPass123 max_idle_conns: 50 data_volume: /data/harbor log: level: warn rotate_count: 10 rotate_size: 100M先说 hostname。这个参数决定后续所有容器的访问地址也决定 k8s 节点拉镜像时填的域名。写成 localhost 或者 127.0.0.1 都会导致集群其他节点解析不到我习惯直接用一个内网域名或者服务器 IP。如果后续要换机器hostname 要跟着迁移变成新地址。http.port 默认 80很多机器上 80 已被占用改成 8080 是最省事的做法。harbor_admin_password 是 web 控制台的初始密码这个必须第一次安装前就改掉否则数据库初始化后密码就写死在 data_volume 里。database.password 是 harbor-db 的 root 密码同理改这个参数要在安装前装完再改就要手工去改数据库里的配置属于自找麻烦。data_volume 我建议独立挂载盘别和系统盘共用一个。日志参数平时不起眼跑几个月后 curl 出 502 往往就是日志把盘打满了所以 rotate 参数建议一开始就写上。如果你之后要开 httpscertificate 和 private_key 两个路径必须真实存在prepare 在生成配置时会检查证书文件路径不对直接报错。证书可以先不管等第 6 章再讲。3.3 prepare 与 install.sh 的执行顺序先配置后安装Harbor 实际启动时用的编排文件是 prepare 根据 harbor.yml 动态生成的。你如果改完 harbor.yml 直接 ./install.shinstall.sh 只会导入镜像、拉起容器编排文件还是旧配置生成的那份于是出现「改了端口没生效、改了 hostname 没生效」之类的问题。正确顺序是cd /opt/harbor cp harbor.yml.tmpl harbor.yml vim harbor.yml ./prepare ./install.sh这里有几个细节。cp 之后先 vim 改完再跑 prepareprepare 会生成 harbor/docker-compose.yml、nginx 的站点配置并创建数据目录。第一次跑 install.sh 会导入镜像包耗时取决于磁盘和内存几分钟到十几分钟都有可能。如果 install.sh 因为某个容器没起来中断了不要重复跑两遍先 docker-compose ps 看哪些容器没 healthy再单独处理。之后每次改 harbor.yml我的习惯是docker-compose down注意不要加 -v-v 会把数据卷删掉然后 ./prepare再 ./install.sh。这条命令链我已经形成肌肉记忆了能挡掉大部分「配置没生效」的疑惑。3.4 端口和数据目录的冲突检查这一节补一个容易被忽略的点Harbor 自身用 nginx 做入口它的 80/443 端口映射到宿主机。如果宿主机上还有别的 nginx、tomcat 占着 80install.sh 起来后端口起不来。先用ss -tlnp检查端口再用 Harbor。数据库端口 5432 和 redis 6379 在编排里是映射到内部网络的理论上不会和宿主机冲突但 docker 的>docker ps --format table {{.Names}}\t{{.Status}} docker-compose ps docker logs harbor-core --tail 50正常的容器列表至少包含 nginx、harbor-core、harbor-portal、harbor-registry、harbor-jobservice、harbor-db、redis、harbor-log 这些角色状态列是 healthy。我第一次在麒麟 V10 上装的时候harbor-db 总是 starting最后发现是数据目录权限不对postgres 用户容器内 uid 10000没有写权限。如果你也遇到容器反复重启优先看两个日志docker logs harbor-db 和 /var/log/harbor/ 下的日志。日志比任何玄学判断都可靠。容器起来后顺手验证一下端口监听和健康接口确认 nginx 入口真的在转发请求而不是容器内部自嗨ss -tlnp | grep -E 8080|443 curl -s http://127.0.0.1:8080/ | head -20curl 返回的 HTML 里能看到 Harbor 的页面标题说明 nginx 和 portal 是通的。如果 curl 超时先查防火墙再查 docker 网络顺序不要反。4.2 网页与 API 验证登录、创建项目、推送镜像控制台和命令行两条路都要验证。浏览器访问 http:// :8080用 harbor_admin_password 指定的账号密码登录。命令行验证用 curl 探测健康接口然后走一遍 docker login、tag、pushcurl -u admin:YourStrongPass2024 http://127.0.0.1:8080/api/v2.0/health docker login reg.k8s.local:8080 -u admin -p YourStrongPass2024 docker tag nginx:1.25 reg.k8s.local:8080/dev/nginx:1.25 docker push reg.k8s.local:8080/dev/nginx:1.25health 接口返回{status:healthy}说明核心服务正常。docker login 这一步能暴露很多问题如果报http: server gave HTTP response to HTTPS client说明你 Harbor 侧开了 HTTPS 或 docker 默认用了 TLS需要给 docker daemon 配置 insecure-registries如果报 connection refused端口没放通去查 firewalld 和监听端口。tag 时注意项目名要和 web 界面里创建的项目一致我示例里的 dev 项目就是先在 web 界面建好的。web 界面建项目的步骤也很简单登录后选「新建项目」填一个名字访问级别选私有。项目建好后命令行推镜像指定的路径就是harbor地址/项目名/镜像名:tag。如果 push 时报 unauthorized多半是账号没有加入该项目成员在项目的「成员」页签里把账号加进去就行。4.3 与 K8s 对接让 kubelet 能拉 Harbor 镜像Harbor 部署好后k8s 集群要正常拉私有仓库镜像需要做三件事。第一件事在每个节点上把 harbor 地址加进 docker daemon 的 insecure-registries如果你用的是 http 或自签证书# /etc/docker/daemon.json 里的内容 { insecure-registries: [ reg.k8s.local:8080 ] }改完重启 docker这一步会重启节点上所有容器生产环境请挑业务低谷做。第二件事在 k8s 里创建一个 docker-registry 类型的 secretkubectl create secret docker-registry regcred \ --docker-serverreg.k8s.local:8080 \ --docker-usernameadmin \ --docker-passwordYourStrongPass2024 \ -n dev第三件事在 pod 的 spec 里声明 imagePullSecrets并写上 harbor 的完整镜像地址spec: imagePullSecrets: - name: regcred containers: - name: app image: reg.k8s.local:8080/dev/nginx:1.25大多数拉取失败发生在这三件的衔接处secret 建好了但 imagePullSecrets 没写或者 daemon.json 改了没重启 docker。还有一点容易漏Harbor 项目如果设为私有拉取时 kubelet 会用 secret 里账号去认证账号要对项目有 pull 权限web 界面里记得把账号加进项目成员。如果多个 namespace 都要用把 secret 复制到对应 namespace再在 yaml 里引用不要在 pod yaml 里手写 dockerconfigjson维护成本太高。5. 避坑指南ARM64 麒麟上部署 Harbor 的四个高频翻车点5.1 harbor-core 反复重启、日志连不上数据库现象install.sh 执行完docker ps 里看到 harbor-core、harbor-jobservice 一直在 restartingdocker logs harbor-core 报 database connection refused 或 password authentication failed。原因我拆包归纳出来两个主要来源。一是 database.password 和 prepare 生成的环境变量不一致尤其改过数据库密码但没重新 prepare二是 /data/harbor 目录属主不对harbor-db 容器UID 10000无法写数据库文件postgres 起不来core 自然连不上。解决先docker logs harbor-db确认 postgres 是否正常如果是目录权限问题执行chown -R 10000:10000 /data/harbor再重启如果是密码问题docker-compose down、./prepare、./install.sh重新生成配置。注意 down 时不要加 -v不然数据卷会被删前面推的镜像全没。5.2 改了 harbor.yml 后端口和 hostname 还是旧的现象vim 改完 harbor.yml 里 http.port 从 80 改成 8080重新跑 install.sh网页还是从 80 访问或 hostname 没变。原因install.sh 只导入镜像并启动容器它不重新生成编排文件。Harbor 的 docker-compose.yml 是 prepare 在 install 前生成的跳过 prepare 等于在用旧配置起新容器。解决把步骤固定成docker-compose down→./prepare→./install.sh。我在 3.3 里写的那条命令链就是为这个问题准备的。改 hostname 后还要注意旧域名登录过 docker 的机器上~/.docker/config.json 里的 auth 保存的是旧地址docker login 新地址前先把旧记录删掉或重新登录。5.3 k8s 节点拉镜像报 x509 证书错误现象Harbor 开了 HTTPSk8s 节点执行 docker pull 时报x509: certificate signed by unknown authority或者 node 侧报http: server gave HTTP response to HTTPS client。原因自签证书没有进节点 docker 的信任列表或者证书 CN 是域名但 harbor.yml 里 hostname 配的是 IP证书校验时域名不匹配自签 CA 一样报错。这是用 IP 直接访问 Harbor 时最容易踩的坑因为证书里默认是不带 IP 的。解决两种方案选一。简单方案是在每台节点的 daemon.json 里配 insecure-registries跳过对 Harbor 地址的 TLS 校验正规方案是把自签 ca.crt 放到/etc/docker/certs.d/reg.k8s.local:8080/ca.crt然后重启 docker。注意端口要写在路径里证书文件名必须叫 ca.crt。生成证书时要把域名和 IP 都写进 SAN避免 hostname 和证书不匹配。如果节点上用的不是 docker 而是 containerd/etc/containerd/config.toml里要配[plugins.io.containerd.grpc.v1.cri.registry.configs]的 tls 信任否则一样的报错。5.4 GC 跑完磁盘没释放/data 分区还在变胖现象web 界面的垃圾回收任务显示 success但 df -h 看 /data 占用没降docker system df 显示 registry 的 blobs 巨大。原因这其实是两个层面。删除镜像 tag 后blob 还留在 registry 里必须跑 GC 才会真正清掉。另外日志没限制大小时/data 下的日志文件、数据库文件也会继续增长。首次部署时如果没配 log 参数跑几个月后盘满属于必然。解决先确认 harbor.yml 里 log.rotate_count 和 rotate_size 配了GC 触发后去 jobservice 看任务是否全部完成平时清理镜像时按项目批量删除无 tag 镜像再在低峰期触发 GC。我的习惯是每月定期做一次「清 tag → GC → 看容量」的循环Harbor 的容量告警配合 Prometheus 也可以接但没有条件的话人工按这套节奏跑也足够稳。6. 进阶技巧自签证书验证、GC 与数据迁移的实操习惯6.1 自签证书用 cert.sh 一把生成包里的 cert.sh 是生成自签证书的辅助脚本。我一般先把它执行一次生成证书放到 /data/cert然后在 harbor.yml 里把 https 段打开指到这两个文件再走 prepare 和 install.sh。验证证书是否生效用一条命令openssl s_client -connect reg.k8s.local:443 -servername reg.k8s.local /dev/null | openssl x509 -text | grep -E Subject:|DNS:输出里的 DNS 列表必须包含 harbor.yml 的 hostname。如果只有 localhost 或者域名对不上docker login 必报 x509 错误。证书生成的坑主要是 SAN 没写全把 hostname 和 IP 一起编进 subjectAltName 就稳了。6.2 GC 与数据迁移的组合拳数据迁移我踩过一次实坑直接在服务运行状态 tar /data/harbor恢复后发现数据库文件不一致Harbor 起不来。从那以后我每次迁移都强制走一遍docker-compose down 停服、rsync /data/harbor 到新机器、保持目录属主一致chown -R 10000:10000、在新机器上改完 hostname 后重新 ./prepare ./install.sh。迁移完用 docker login 和新节点拉一次镜像才算验证通过。GC 的触发也要配合数据迁移的节奏迁移前先清一批无用镜像并跑一次 GC能让迁移数据量小很多。6.3 K8s 节点滚动重启的技巧daemon.json 改完免不了要重启 docker生产环境不想全部节点同时重启的话用 kubectl drain 一个节点处理完再 uncordon逐个滚过去。低峰期操作单节点的容器拉起时间通常在几分钟内。如果嫌慢用 systemctl reload docker 行不行注意 docker 的 daemon.json 改动必须 restart 才会对 insecure-registries 生效reload 不生效。我从那以后每次部署都强制先走「确认架构 → 定 hostname → 生成证书 → 配 harbor.yml → 配 k8s node」这套顺序再把日志和 GC 参数写上基本不会再翻车。希望帮到你。本文还有配套的精品资源点击获取