这两年只要公司内部做容器化改造,私有镜像仓库基本是第一个被拎出来的基础设施。我自己经手过好几个项目,从一开始直接用原生Docker Registry,到后来换成Harbor,体验差别非常明显。Harbor是基于Docker Registry做的企业级扩展,把权限、复制、扫描、审计这些能力都补全了,而且带一套很直观的Web界面,日常维护省心很多。这篇文章把Harbor的安装和日常使用完整过一遍,从环境准备、配置选型、证书处理,到推拉镜像、配置复制规则、垃圾回收,每个环节我都按自己的实操经验来讲,适合正在搭建内部镜像仓库的运维、开发或者小团队负责人参考。
1. 先搞清楚Harbor到底解决了什么问题
1.1 原生Docker Registry的几个短板
如果只是搭一个临时环境,直接跑一个registry容器确实也行:
docker run -d -p 5000:5000 --name registry registry:2但这个方案一旦放到团队协作里,问题马上就来了。第一个坑是没有权限控制,谁都能推谁都能删,一旦有人误操作,镜像可能就没了。第二个是没地方看日志,出了问题查不到是谁在什么时候动过什么镜像。第三个是没有Web界面,想看仓库里有哪些镜像版本只能敲命令。第四个更麻烦,多机房之间同步镜像基本靠手动拉推,非常费劲。这几个短板在项目规模小的时候还能忍,人一多、镜像一多,维护成本成倍往上走。
Harbor把这几个短板全部补齐了。它在Docker Registry基础上加了一层完整的管理体系,包括基于角色的访问控制(RBAC)、项目隔离、镜像复制、漏洞扫描、日志审计,还有一个很直观的Web界面。用户可以直接在浏览器里浏览项目下的镜像列表、查看tag信息、看到最近的操作记录,这些体验对团队协作非常关键。
1.2 Harbor的核心能力拆解
- 项目管理:以项目为单位划分空间,项目内可以有多个镜像仓库,支持公开和私有两种可见性。
- 权限模型:支持用户、用户组、机器人账号,项目角色分为管理员、维护者、开发者、访客等,权限边界清晰。
- 镜像复制:把一个实例的镜像异步复制到另一个Harbor实例或者第三方Registry,支持多机房、灾备场景。
- 漏洞扫描:内置Trivy扫描器,可以扫描镜像里的漏洞并生成报告,还可以按漏洞级别设置阻断策略。
- 垃圾回收:回收未被任何镜像引用的blob数据,避免磁盘空间持续膨胀。
- 审计日志:记录关键操作行为,方便出问题时追溯。
这些能力让Harbor基本成了私有镜像仓库的默认选项。后面我就围绕安装和使用这两条主线,把整个流程完整走一遍。
2. 部署前的准备与方案选型
2.1 硬件和软件要求
Harbor 官方给的最低配置要求不算高,但实际使用时要结合规模调整。我建议至少 2 核 4GB 内存起步,如果开启了 Trivy 扫描或者并发拉取镜像比较多,4 核 8GB 会比较稳妥。磁盘方面,data_volume是镜像实际存储位置,优先用 SSD,至少预留 50GB,具体看你们的镜像增长速度和保留策略。
软件环境方面,Docker 需要 20.10 以上,操作系统用主流 Linux 发行版都行,CentOS 7、Ubuntu 20.04、Debian 等常见版本我都跑过。需要特别注意的是,CentOS 7 这类老系统容易遇到内核版本和 iptables 相关的问题,轻则推送镜像时连接超时,重则 Harbor 的各个容器之间网络不通。另一个容易忽略的点是 Docker Compose 的版本,Harbor v2.x 走的是插件版的docker compose命令,而不是老的docker-compose,安装前最好先确认一下版本。
注意:Harbor 的安装脚本会检查本机的 Docker 和 Compose 环境,如果环境不满足要求会在第一步就报错,提前检查能省掉不少折腾时间。
2.2 在线版和离线版怎么选
Harbor 官方提供在线安装包和离线安装包两种。在线包体积小,安装时会从网上拉取镜像,适合服务器能顺畅访问外部镜像源的场景。离线包把所有组件镜像都打包好了,安装过程不依赖网络,适合内网离线环境。
我个人的习惯是:只要能拿到官方离线包,一律用离线包。原因很简单,在线包安装时要从外部拉好几个镜像,网络稍微一抖就失败,而且安装脚本的重试机制并不完善,中间断了要清理掉重新来,很烦。离线包虽然下载时体积大一点,但安装过程稳定得多,几台机器装完基本不会出幺蛾子。下载时注意选择对应 CPU 架构的包,比如 amd64 平台的harbor-offline-installer-v2.x.x.tgz,解压后目录里会有install.sh和harbor.yml.tmpl。
2.3 单机部署还是高可用部署
Harbor 部署形态主要分两种。一种是单机模式,用 docker compose 把 Harbor 的各个组件跑在一台机器上,适合测试环境、小团队、镜像量不大并且对可用性要求不高的场景。另一种是高可用模式,Harbor 自身的元数据放到外部 PostgreSQL,镜像存储放到外部对象存储如 MinIO 或云对象存储,多个 Harbor 实例共用这些外部组件,前面再加负载均衡对外提供统一入口,适合生产环境核心业务。
如果团队规模不大,建议先别急着上高可用。Harbor 的高可用不是单纯多跑几个容器就行,数据库、对象存储都需要一并迁移,维护复杂度是直线上升的。我见过不少团队在十几个人、几十个项目的规模下,一台单机 Harbor 运行得很稳,偶尔磁盘空间不够,清一清垃圾回收就解决了。等镜像量上来、需要跨机房容灾的时候,再考虑复制规则或者高可用改造,节奏更合理。
3. 安装实操:从下载到跑起来
3.1 下载解压和初始化配置
假设我现在部署一台新的 Harbor 服务器,操作系统是 Ubuntu 20.04,内网 IP 是 192.168.1.100,计划用域名harbor.example.com对外提供访问。先把离线包上传到服务器,然后解压并复制出配置文件:
tar -zxvf harbor-offline-installer-v2.11.1.tgz cd harbor cp harbor.yml.tmpl harbor.yml第一次安装时,harbor.yml是最关键的配置文件。我最常改的几个参数如下:
hostname:对外访问的地址,可以是域名或 IP。如果前面有反代,就写反代的对外域名。http.port:默认 80 端口。如果机器上已经有 Web 服务占用 80,可以改成 8080,我遇到过好几次端口冲突。https.port:默认 443。如果暂时没有证书,可以直接把 https 配置块注释掉,先用 http 跑通流程。harbor_admin_password:管理员初始密码,必须改成强密码,至少 8 位并且包含大小写字母和数字。database.password:内部数据库密码,同样换成复杂密码,别留在默认值。data_volume:镜像数据存放目录,默认是/data,建议改成独立数据盘,比如/data/harbor,避免和系统盘混在一起。
3.2 证书的两种处理方式
如果 Harbor 只在纯内网跑,用 http 也能先跑起来。但企业环境早晚要走 https,而且 Kubernetes 集群拉镜像时,如果没有可信证书,每个节点都要额外配置,维护成本很高,所以我建议一开始就部署 https。
最常用的办法是生成自签名证书,流程也不复杂。先生成 CA 私钥和 CA 证书:
openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt再生成服务端私钥和证书请求:
openssl genrsa -out harbor.key 4096 openssl req -new -key harbor.key -out harbor.csr -subj "/CN=harbor.example.com"现在的 Docker 客户端对证书校验很严格,证书里必须带 Subject Alternative Name,也就是 SAN。建一个ext.cnf文件:
subjectAltName=DNS:harbor.example.com,IP:192.168.1.100然后用 CA 签发服务端证书:
openssl x509 -req -in harbor.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out harbor.crt -days 3650 -sha256 -extfile ext.cnf把harbor.crt和harbor.key放到固定目录,比如/certs下,然后在harbor.yml中填入:
https: port: 443 certificate: /certs/harbor.crt private_key: /certs/harbor.key如果公司有统一的证书签发体系,也可以让它签发服务端证书,但同样要注意证书必须包含域名或 IP 的 SAN,否则各种客户端照样不认。
这里有个我踩过的坑:有些同学图省事只配置 http,装完之后 Kubernetes 节点要从 Harbor 拉镜像,每个节点的 docker daemon 都要去改insecure-registries。看起来只是改一个配置,但节点一多,漏掉一个,那个节点的 Pod 就卡在ImagePullBackOff,排查起来很费时间。所以内网环境我强烈建议一步到位配好 https。
3.3 执行安装脚本
配置完harbor.yml,执行安装脚本:
./install.sh脚本会先检查 docker 和 docker compose 环境,然后按顺序启动 Nginx、Core、Registry、数据库等容器。如果想启用漏洞扫描功能,加一个参数:
./install.sh --with-trivy首次启动需要加载的镜像比较多,离线包情况下一般几分钟内能完成。安装结束后用docker ps查看,核心容器都处于 Up 状态,Harbor 就装好了。我建议第一时间打开浏览器访问https://harbor.example.com,用 admin 账号登录确认 Web 界面正常。
登录后第一件事是修改管理员密码,同时创建普通用户和机器人账号。不要长时间保留默认密码,内网环境很多人容易忽视这一点,实际上风险不小,尤其是当 Harbor 同时暴露给多个团队使用时。
3.4 验证核心功能
部署完成后不要直接宣布完工,至少要验证三件事。第一,浏览器能打开 Harbor 页面并正常登录。第二,服务器本地能执行docker login https://harbor.example.com并且认证成功。第三,推一个测试镜像再拉回来,确认读写链路是通的。
我通常推一个几MB的小镜像:
docker tag busybox:latest harbor.example.com/library/busybox:test docker push harbor.example.com/library/busybox:test推送成功后再删除本地镜像,执行docker pull拉回来,能拉下来就说明基本链路没问题。如果中间有证书或网络问题,都会在docker login和docker push阶段暴露出来,这时候排查会比后面接入真实项目再排查省事得多。
4. 日常使用的核心操作
4.1 项目创建与权限分配
Harbor 里的基本逻辑是:项目是权限边界,镜像归属于某个项目。登录后用管理员账号先创建项目,比如company-platform,然后选择公开或私有。开发环境我习惯建一个公开的基础镜像项目,放操作系统镜像、中间件镜像,团队内部直接拉取;业务镜像则单独放到私有项目里,只有指定成员能访问。
权限分配这块,Harbor 的角色分得很细。管理员拥有项目内所有权限;维护者可以管理项目配置;开发者可以推送和拉取镜像;访客只能拉取。实际操作中,我通常给开发人员分配“开发者”角色,给负责基础架构的同学分配“维护者”角色。对自动化平台接入,更推荐用机器人账号,比如 CI/CD 流水线用一个机器人账号推送,权限只限定到指定项目,这样即使密钥泄露也不会影响其他项目。
4.2 客户端登录与镜像操作
开发同学在本地推送镜像时,流程非常直观。先登录:
docker login harbor.example.com -u devuser然后给本地镜像打上 Harbor 的完整路径标签:
docker tag myapp:1.0.0 harbor.example.com/company-platform/myapp:1.0.0最后推送:
docker push harbor.example.com/company-platform/myapp:1.0.0拉取镜像时同理,注意项目可见性。如果项目是私有的,客户端必须登录后才有权限拉取;Kubernetes 节点拉取私有项目镜像,需要提前在节点上配置imagePullSecret,这是 K8s 侧的常见操作,但要和 Harbor 这边的用户、密码对应起来,别搞混账号。
有个细节容易忽略:镜像版本标签不要随便覆盖。Harbor 默认没有强制保护,只要权限够,同名 tag 可以重新推送,历史 tag 就被覆盖了。发布回滚时如果发现 tag 指向的镜像变了,会很麻烦。可以在项目配置里开启禁止覆盖同名 tag 的策略,或者制定固定的 tag 命名规范,比如带上版本号和构建号,这样生产环境出问题时能精确定位到具体镜像。
4.3 配置镜像复制规则
镜像复制是 Harbor 特别实用的功能。假设公司有两个机房,业务同时运行在两台环境,镜像只要构建一次,就可以通过复制规则同步到另一个机房的 Harbor。具体操作是先添加目标注册表:在 Harbor 管理界面找到复制管理,新建目标,填写目标 Harbor 的地址、用户名、密码或者机器人账号。
然后新建复制规则,选择源项目,比如company-platform,目标选择刚才添加的注册表,触发方式可选手动、定时或事件驱动。事件驱动意味着源项目每推送一个新镜像,会自动触发同步,这种模式最适合构建交付流程。需要注意复制规则同步的是整个项目还是具体仓库,按实际需求选择,避免把不该同步的镜像也传过去。多机房场景下,我一般只同步生产项目,测试环境的基础镜像不同步,防止测试噪声污染生产仓库。
4.4 镜像扫描和安全策略
镜像扫描方面,Harbor v2.x 默认内置 Trivy。安装时加了--with-trivy,界面里就能对单个镜像发起扫描。扫描结果按漏洞严重程度分类展示,Critical、High、Medium、Low 分得很清楚,还会给出漏洞描述和修复建议。我建议在项目配置里开启自动扫描,每次推送新镜像都自动跑一遍,同时可以设置阻断策略,比如高危漏洞数量超过阈值就阻止镜像被拉取。
这个策略在真实工作中很实用。有一次某团队把存在多个高危漏洞的镜像直接推到生产项目里,幸好项目开启了阻断策略,拉取请求直接报错,后来他们补了依赖库版本重新构建才通过。如果没有这道防线,漏洞镜像上线后要来回通知、回滚,成本高得多。
5. 常见问题与排查技巧实录
5.1 自签名证书带来的各种不信任
自签名证书这套方案虽然能用,但坑确实多。最常见的表现是浏览器访问 Harbor 显示不安全警告,docker login时报certificate signed by unknown authority,Kubernetes 节点拉镜像时报x509: certificate signed by unknown authority。
排查思路很简单:检查harbor.yml里的证书路径和证书内容是否匹配,用 openssl 直接看证书信息:
openssl x509 -in harbor.crt -noout -text | grep "Subject Alternative Name"如果没有 SAN,或者 SAN 里的域名和实际访问地址不一致,肯定报错。解决办法是重新生成带正确 SAN 的证书,并重启 Harbor 容器。另外,客户端 Docker 还要把 CA 证书加到受信任区,最简单的方式是把ca.crt复制到每台客户端的/etc/docker/certs.d/harbor.example.com/目录下,重启 Docker 后就不会再报未知权威了。节点多的时候可以用配置管理工具批量下发,手工一台台加太容易漏。
5.2 推送镜像提示 unauthorized
这个报错最常见的原因是登录信息不对或者项目权限不够。先确认docker login有没有成功,再确认推送的镜像路径里项目名称是否写对。Harbor 默认有一个library项目,但实际项目中可能并没有这个名称,写错了就会提示unauthorized。另外,如果是机器人账号,要确认权限是否覆盖了目标项目,机器人账号默认只对指定项目有效,去别的项目推送就会失败。
还有一种情况容易被忽略:在开启了镜像签名或 tag 保护的项目里,某些 tag 被标记为不可覆盖,推送同名的不同镜像会失败。这时候去项目配置里看保护规则,或者直接换一个新的 tag 版本,就能绕过问题。
5.3 磁盘空间被镜像写满
Harbor 跑一段时间后,磁盘占用上涨是正常现象。data_volume目录下会堆积大量 blob 数据,有些是被多个镜像共用的,有些是历史 tag 不再使用但还没被清理的。最简单的处理方式是在 Harbor 的管理页面里找到垃圾回收,启动 GC,系统会清理没有被任何镜像引用的 blob。
但 GC 不是说点了就立刻变小。实际操作中我发现,删除镜像 tag 后,被删除 tag 引用的 blob 只有在 GC 启动后才会真正释放。建议把 GC 做成周期性任务,比如每周一次,放在业务低峰期跑,避免影响拉取速度。另外,数据盘要提前挂载成独立分区,防止data_volume把系统盘塞满,否则整个机器都可能卡住,数据库和 Web 服务一起出问题,处理起来很被动。
5.4 端口冲突与反代配置
Harbor 默认占用 80 和 443 端口,机器上如果已有 Nginx 或其他 Web 服务,肯定会端口冲突。这种情况下要么换掉 Harbor 的http.port和https.port,要么让前面的一层 Nginx 做反向代理,把请求转发到 Harbor 的实际端口。我实际遇到更多的情况是公司已经有统一的域名和网关,Harbor 不能直接暴露 80 和 443,此时可以选择只给 Harbor 配内网端口,再由统一网关做 TLS 终止和转发。
这时需要特别注意hostname的配置。如果 Harbor 的hostname写成内网 IP,而客户端通过公司统一域名访问,登录后 Harbor 页面里显示的访问地址还是内网 IP,跨网段访问就会出问题。正确做法是harbor.yml里的hostname配置成对外统一域名,并在上面的反代层处理证书和转发。
6. 运维中的几个实用建议
6.1 备份策略要落到可恢复验证
Harbor 的数据主要分为两部分:数据库里的元数据和data_volume中的镜像 blob。备份时不能只把data_volume拷贝下来,数据库里存着项目权限、复制规则、扫描策略这些关键信息,丢了这些,镜像就算还在,管理体系和权限也会乱套。建议定期对数据库做导出备份,同时给data_volume做快照。这里我特别想说一句:备份最好能在备用机器上真实恢复一次,确认恢复流程可用,不然备份始终只是心理安慰。
6.2 升级节奏要放慢
Harbor 升级不建议追新。先看升级路径说明,确认从当前版本到目标版本是直接支持还是需要逐级升级。比如跨大版本升级,如果中间结构变化很大,最好先在一台测试环境完整走一遍。我每次升级都遵循固定流程:先备份,再在另一台机器搭建新版本,把数据导入验证,确认所有项目、复制规则、扫描策略都正常,最后才动生产。升级前还要注意旧版本的配置项是否在新版本被废弃,harbor.yml的字段变动很常见,直接拿旧配置跑新版本容易报错。
6.3 多实例之间按环境隔离
如果公司有多个环境,比如测试、生产分属不同 Harbor 实例,镜像流程可以设计成“构建一次、测试验证、复制到生产”。测试环境 Harbor 开放给开发团队频繁推送,生产环境 Harbor 只接收来自测试实例的复制,或者只允许自动化任务推送。这种模式能大幅降低人为误操作影响生产的机会。配合机器人账号和复制规则,整个链路完全可以自动化。
6.4 从第一天就规范端口、域名、证书
从第一天部署 Harbor 开始,就应该把端口、域名、证书的对应关系梳理清楚。域名建议单独规划,不要和业务域名混在一起;证书有效期到期前一个月做好续期提醒;机器人账号要定期轮换。这些看起来都是小事,但越往后越能感受到规范的重要性。我见过很多临时拼起来的镜像仓库,最后都栽在证书过期和域名变更上,那种排查成本远超一开始多花的那点时间。
最后说点个人体会。Harbor 这个项目本身并不复杂,真正复杂的是围绕它建立的工作流。安装只是半天的事,后续的项目规划、权限设计、备份策略、扫描策略才是长期要维护的东西。如果你正在搭第一个 Harbor,我的建议是先按单机、https、Trivy 扫描、每周 GC 这套组合上线,跑顺之后再逐步加复制规则和高可用改造。这个节奏是我踩过不少坑之后摸索出来的,应该能让你的落地过程顺利很多。