☰
Harbor私有镜像仓库实战:从部署、权限到高可用运维避坑指南
2026/10/26 3:43:20 网站建设 项目流程

1. 为什么我要自己搭一套私有镜像仓库

第一次认真考虑自建镜像仓库,是因为一次很尴尬的事故。团队做容器化改造,所有业务镜像都往公共仓库推,结果某天公共仓库限流,CI 流水线全线卡死,十几个服务等着发布,运维那边只能干瞪眼。那次之后我就下定决心,得在自己可控的环境里放一套镜像仓库,把镜像的"存取权"握在自己手里。Harbor 就是在这个背景下进入视野的——它是一个开源的容器镜像仓库项目,能存镜像、能管权限、能做镜像扫描、还能给镜像签名,基本覆盖了企业内做镜像治理的全部刚需。

说白了,Harbor 解决的核心问题就三个:镜像放哪儿、谁能动、动过之后安不安全。公共仓库能解决"放哪儿",但"谁能动"和"安不安全"这两件事,在多人协作、多环境隔离的场景下,公共仓库给不了你足够的控制力。Harbor 把这三件事一次性打包解决:项目级别的 RBAC 权限、基于角色的访问控制、镜像漏洞扫描、镜像复制、审计日志、配额管理,这些能力组合起来,才让它成为很多团队私有镜像仓库的首选。

这篇内容适合谁看?如果你正在做容器化落地,团队里镜像越堆越多、权限越来越乱、安全审计开始被提上日程,那这套东西你迟早要碰。如果你只是想本地跑个 demo 存两个镜像,那用不着 Harbor,一个轻量 registry 就够了。我下面讲的是真正要在团队里长期跑起来的那套方案,包括架构选型、部署细节、权限设计、日常运维和踩过的坑,尽量让你少走弯路。

2. 整体架构设计与选型思路拆解

2.1 Harbor 的组件构成与数据流向

Harbor 不是一个单体程序,它是一组服务拼起来的。核心组件包括:proxy(反向代理,通常用 nginx)、core(主服务,处理 API 和业务逻辑)、registry(真正存镜像的组件,基于开源 registry)、database(存元数据,默认 PostgreSQL)、redis(缓存和任务队列)、jobservice(异步任务,比如镜像复制、扫描),以及可选的trivy 扫描器、notary 签名服务。这些组件通过容器编排起来,对外只暴露一个入口。

理解这个结构很重要,因为它直接决定了你排查问题的思路。比如镜像推不上去,可能是 proxy 的证书问题,可能是 core 的认证问题,也可能是 registry 的存储问题,还可能是 database 连不上导致 core 起不来。你得知道请求是怎么流的:客户端先打到 proxy,proxy 转发给 core 做认证鉴权,认证通过后 core 返回一个 token,客户端拿着 token 直接和 registry 交互完成镜像的存取。这个"认证和传输分离"的设计是 Harbor 权限体系的基础,也是很多人第一次配的时候容易懵的地方。

2.2 为什么选 Harbor 而不是其他方案

市面上做私有镜像仓库的选择其实不少,我简单对比一下我考虑过的几个方向。轻量 registry 最省事,一个容器起来就能用,但它没有权限体系、没有 Web 界面、没有扫描,团队一多人就管不住。某些商业方案功能全但成本高,小团队用不起。Harbor 的定位刚好卡在中间:开源免费、功能完整、社区活跃、文档齐全,而且它是 CNCF 毕业项目,长期维护有保障。

更关键的是 Harbor 的几个能力正好戳中企业场景的痛点。项目隔离让你可以按业务线或环境划分镜像空间;RBAC让你能精细控制谁能推、谁能拉、谁只能看;镜像扫描让你在镜像上线前就知道有没有高危漏洞;镜像复制让你能在多机房或多集群之间同步镜像;审计日志让你事后能追溯谁动了什么。这些能力单拎出来都不稀奇,但整合在一个系统里、配置起来还不算太复杂,这就是 Harbor 的价值。

2.3 部署形态的选择:单机还是高可用

部署形态上,我建议先想清楚你的规模。如果只是内部小团队、镜像量不大、对可用性要求没那么苛刻,单机部署完全够用,用 docker-compose 一把起来,维护成本低。但如果你要承载多个集群的镜像拉取、或者镜像仓库挂了会影响生产发布,那就得考虑高可用部署,通常是多实例加共享存储(对象存储或共享文件系统)加外部数据库。

我这里给个实际的判断标准:如果镜像仓库宕机一小时内你能接受、并且有备用方案,单机就行;如果镜像仓库是发布链路的强依赖、宕机就发不了版,那就上高可用。别一上来就追求高可用,那会把部署复杂度拉高好几个档次,小团队维护不过来反而更容易出事。我见过不少团队为了"高可用"搞了一套复杂架构,结果因为没人真正懂,出问题时恢复得比单机还慢。

3. 部署实操:从零把 Harbor 跑起来

3.1 环境准备与前置检查

我以单机 docker-compose 部署为主线讲,这是绝大多数团队起步的方式。前置条件有这么几个:一台 Linux 机器(我习惯用较新的稳定版发行版)、装好 Docker 和 docker-compose、至少 4 核 8G 的配置(镜像多了存储要单独规划)、一个能解析的域名或者至少一个固定 IP。

有几个前置检查特别容易被忽略,我列一下。第一,磁盘空间要单独规划,镜像很吃存储,建议给 Harbor 的数据目录单独挂一块盘,别和系统盘混在一起,否则镜像一多系统盘满了整个机器都受影响。第二,时间同步要确保,Harbor 的 token 认证对时间敏感,机器时间偏差大了会出现莫名其妙的认证失败。第三,端口占用要确认,Harbor 默认用 80 和 443,如果机器上已经有 nginx 占了,要么改 Harbor 的端口,要么把前面的 nginx 停掉。

# 检查端口占用 ss -tlnp | grep -E ':80|:443' # 检查时间同步状态 timedatectl status # 检查磁盘 df -h /data

提示:如果你打算用 HTTPS(强烈建议),提前把证书准备好。自签证书也行,但要记得把 CA 分发到所有需要访问 Harbor 的机器上,否则 docker 拉镜像会报证书错误。

3.2 下载与配置 harbor.yml

从官方发布页拿到离线安装包,解压后会看到一个harbor.yml.tmpl模板。复制一份改成harbor.yml,然后重点改这几个地方。hostname填你的域名或 IP,这个值会写进镜像地址里,改起来很麻烦,一开始就要定好。https段配置证书路径,harbor_admin_password设一个强密码,data_volume指向你规划好的数据盘目录,database段如果单机就用内置的 PostgreSQL。

还有一个参数值得单独说:storage_service。默认是本地文件系统,镜像存在 data_volume 下面。如果你后面想扩展到对象存储,这里可以配 s3 或 oss。我的经验是,单机阶段用本地存储最省心,等真到了要多实例高可用的时候再换对象存储,别一开始就上对象存储给自己增加调试成本。

hostname: harbor.example.internal https: port: 443 certificate: /data/certs/harbor.crt private_key: /data/certs/harbor.key harbor_admin_password: YourStrongPassw0rd data_volume: /data/harbor storage_service: filesystem: rootdirectory: /storage

配置改完,执行./install.sh,脚本会生成 docker-compose 文件并拉起所有容器。第一次装的时候我建议加--with-trivy把扫描器一起装上,省得后面再补。装完用docker-compose ps看下容器状态,正常情况下应该全是 Up。

3.3 首次登录与基础验证

装完之后浏览器访问你的 hostname,用 admin 和你设的密码登录。第一件事是改掉 admin 的默认密码(如果你在配置文件里设的就是强密码,这步可以跳过,但还是要确认一下)。第二件事是建一个测试项目,比如叫library或test,然后试着推一个镜像上去验证整条链路。

# 登录(注意地址要和 hostname 一致) docker login harbor.example.internal # 给本地镜像打 tag docker tag nginx:latest harbor.example.internal/test/nginx:v1 # 推送 docker push harbor.example.internal/test/nginx:v1

推成功之后回到 Web 界面,在项目里能看到这个镜像和它的 tag,说明存储、认证、registry 这条链路是通的。如果推失败,先看报错类型:unauthorized多半是登录或权限问题,certificate是证书问题,connection refused是网络或端口问题。这个分类排查法能帮你快速定位到是哪一层出的问题。

4. 权限体系与项目治理的落地细节

4.1 项目、用户与角色的关系设计

Harbor 的权限模型是"项目为中心"的。镜像归属于项目,用户通过被授予项目角色来获得对项目内镜像的操作权限。角色有几种:项目管理员能管项目配置和成员,开发者能推拉镜像,访客只能拉,受限访客只能拉特定仓库。系统层面还有系统管理员,能管所有项目和用户。

我实际落地时的做法是:按业务线或环境建项目,比如prod-payment、test-payment、prod-order这种命名,一眼能看出归属和环境。然后按团队建用户组,把组授予项目角色,而不是一个个用户去加。这样人员变动时只改组,不用动项目配置。这个习惯能省掉大量后期维护工作,我见过项目成员一个个手动加的,人一多就乱套。

4.2 机器人账号与 CI 集成

CI 流水线推镜像不能用真人账号,得用机器人账号(robot account)。机器人账号是绑定到项目或系统级别的,有独立的 token,权限可以精确到推或拉。给每个 CI 流水线建一个专属的机器人账号,好处是权限最小化、出问题能定位到具体流水线、token 泄露了只影响一个账号。

建机器人账号的时候,权限勾选要克制。只推镜像的流水线就只给 push 权限,不要图省事给全权限。token 生成后只显示一次,记得立刻存到 CI 的密钥管理里。我踩过的坑是:早期图方便用 admin 账号在 CI 里推镜像,后来要审计"谁推了什么"的时候完全查不出来,因为全是 admin。换成机器人账号之后,审计日志里每条推送都能对应到具体流水线,排查问题方便太多。

4.3 配额与垃圾回收策略

镜像越堆越多是必然的,得提前定策略。Harbor 支持项目配额,可以限制单个项目能用的存储量,防止某个项目把磁盘吃满影响所有人。我一般会给测试环境的项目设一个较小的配额,生产环境设大一些,这样测试环境乱推镜像也不会挤占生产空间。

垃圾回收(GC)是另一个必须定期做的事。删掉镜像 tag 之后,底层的 blob 不会立刻释放,得跑 GC 才能回收空间。GC 可以在 Web 界面手动触发,也可以配成定时任务。我的经验是每周跑一次,放在业务低峰期,因为 GC 期间仓库会短暂只读。另外要注意,GC 有"是否删除无 tag 的 manifest"的选项,勾选前想清楚,有些团队依赖无 tag 的镜像做中间层,删了会影响拉取。

治理项建议策略说明
项目配额测试环境小、生产环境大防止单项目吃满磁盘
镜像保留按 tag 数量或时间保留避免历史版本无限堆积
垃圾回收每周低峰期执行回收已删除镜像的底层数据
审计日志保留至少 90 天满足事后追溯需求

5. 镜像扫描、复制与高可用扩展

5.1 漏洞扫描的配置与解读

Trivy 扫描器装上之后,镜像推上来会自动触发扫描(也可以配成手动)。扫描结果会给出漏洞等级分布:严重、高、中、低。我的用法是在 CI 里加一道卡点:如果镜像有"严重"级漏洞,流水线直接失败,不允许推到生产项目。这个卡点能挡住大部分因为基础镜像过期带来的风险。

但扫描结果不能一刀切。有些漏洞在特定运行环境下根本不可达,全卡死会导致大量误报、拖慢发布。我的做法是分级处理:严重级必须修,高级评估后决定,中低级记录跟踪。另外要定期更新 Trivy 的漏洞库,否则扫出来的结果是过时的。Harbor 的扫描器可以配自动更新,记得打开。

5.2 多环境镜像复制的实践

当你有多个集群或多个机房时,镜像复制就派上用场了。Harbor 支持基于规则的复制:源项目里的镜像可以自动同步到目标 Harbor 实例。典型场景是"测试环境验证通过的镜像,自动同步到生产环境的仓库",或者"总部仓库同步到分支机构仓库"。

配复制规则时要注意触发模式:可以按事件触发(推上来就同步),也可以定时触发。事件触发实时性好但可能同步太频繁,定时触发适合对实时性要求不高的场景。还有过滤规则要配好,别把整个项目全同步过去,按 tag 模式过滤,比如只同步release-*的 tag。我见过没配过滤导致把测试镜像也同步到生产仓库的,虽然不影响运行,但仓库里一堆垃圾镜像很难看。

5.3 从单机到高可用的演进路径

前面说了单机起步,那什么时候该演进到高可用?我的判断是:当镜像仓库成为发布链路的单点、并且团队对停机零容忍时。演进路径一般是:共享存储(对象存储)+ 外部数据库(PostgreSQL 主从)+ 多 Harbor 实例 + 前置负载均衡。这个改造不是一蹴而就的,建议先在测试环境验证整套架构,再动生产。

改造过程中最容易出问题的是存储迁移。从本地文件系统迁到对象存储,需要用 Harbor 自带的迁移工具或者手动同步数据,迁移期间仓库要停写。我的建议是挑一个发布窗口,提前演练一遍迁移流程,把耗时和回滚方案都摸清楚,别在生产上第一次试。

6. 常见问题排查与运维避坑实录

6.1 推送拉取失败的典型排查路径

镜像推拉失败是最常见的问题,我整理了一个排查顺序。先看客户端报错信息,x509开头的是证书问题,unauthorized是认证问题,denied是权限问题,no such host是 DNS 问题。然后确认 docker login 的地址和 harbor.yml 里的 hostname 完全一致,不一致会导致 token 里的 audience 对不上,认证失败。再然后检查证书链,自签证书要把 CA 装到客户端的信任链里,否则 docker 不认。

还有一个很隐蔽的坑:docker 的 insecure-registries 配置。如果你用 HTTP 或者自签证书,需要在客户端的 daemon.json 里把 Harbor 地址加到 insecure-registries,改完要重启 docker。这个配置在每台需要访问 Harbor 的机器上都要做,包括 CI 的构建节点。我踩过一次,本地能推、CI 推不了,查了半天才发现是 CI 节点没配这个。

6.2 存储与数据库的运维要点

存储方面,定期看磁盘使用率是基本功。除了看总量,还要看增长趋势,镜像增长快的时候要提前扩容。本地存储扩容相对简单,加盘挂载就行;对象存储则要注意配额和生命周期策略。另外,备份不能只备份数据库,镜像数据本身也要考虑,虽然镜像可以从构建流水线重新生成,但历史版本丢了会影响回滚能力。

数据库方面,单机内置的 PostgreSQL 够用,但要定期备份。Harbor 的元数据(项目、用户、权限、镜像 tag 信息)都在数据库里,数据库丢了等于仓库配置全丢。备份策略我一般用每天全量加 binlog 增量,保留一周。恢复演练也要做,别备份了从来没恢复过,真出事的时候发现备份是坏的。

6.3 常见问题速查表

现象可能原因处理方向
推送报 unauthorized未登录或 token 过期重新 docker login
推送报 denied账号无 push 权限检查项目角色或机器人账号权限
拉取报证书错误CA 未安装或证书过期安装 CA 或更新证书
Web 打不开proxy 容器异常或端口冲突查容器状态和端口占用
扫描一直 pending扫描器未启动或队列堵塞检查 trivy 容器和 jobservice 日志
GC 后空间没释放有镜像仍引用 blob确认镜像已全删再跑 GC
复制任务失败目标端网络或认证问题检查目标地址连通性和凭据

6.4 我踩过的几个真实坑

第一个坑是升级没看 release note。Harbor 跨大版本升级有数据库迁移,有些版本升级前必须先升到中间版本,跳版本升会失败。我建议升级前一定读官方的升级说明,并且在测试环境先升一遍。升级前还要备份数据库和配置文件,出问题能回滚。

第二个坑是日志把磁盘写满。Harbor 的容器日志默认可能无限增长,跑久了把磁盘吃满,然后整个仓库挂掉。解决办法是配 docker 的日志轮转,限制单个日志文件大小和保留数量。这个配置在 daemon.json 里做,改完重启 docker。

第三个坑是机器人账号 token 过期。机器人账号的 token 可以设有效期,设短了安全但容易过期导致 CI 失败,设长了安全风险高。我的折中是设一个较长的有效期,同时在 CI 里做好失败告警,token 快过期时提前轮换。轮换的时候新旧 token 并行一段时间,避免切换瞬间流水线全挂。

7. 我个人的一些使用体会

这套东西我从单机一路用到多实例,最大的感受是:Harbor 的能力很全,但全不等于都要用。一开始别把所有功能都打开,先把镜像存取和权限跑顺,再逐步加扫描、加复制、加高可用。每加一个能力都要配套相应的运维流程,否则功能开了没人管,反而成了负担。

另外一个体会是命名和规范比技术选型更重要。项目怎么命名、tag 怎么打、谁能推哪个环境,这些规范定清楚了,Harbor 用起来就顺;规范不清楚,再好的工具也管不住混乱。我现在的习惯是项目名带环境和业务线、tag 用语义化版本加 git commit 短哈希、生产项目的推送权限只给发布流水线的机器人账号,这几条定下来之后,镜像治理基本就没出过大乱子。

最后分享一个小技巧:Harbor 的 Web 界面里有"审计日志",很多人不用,但它排查问题特别好使。谁在什么时候推了哪个镜像、删了哪个 tag、改了哪个项目配置,全都有记录。有次生产镜像被误删,就是靠审计日志定位到具体操作和时间点,快速恢复了。建议你把它当成日常排查的第一入口,比翻容器日志快得多。

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

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

立即咨询