
做了这么多年后端我越来越觉得“制品管理”这件事是被大多数团队低估的基础设施。项目多了以后镜像散落在各个服务器上哪个版本部署在哪儿全靠聊天记录出了问题根本没法追溯。后来我认真调研并实践过几款制品管理工具其中Harbor是绕不开的事实标准而Hadess这类轻量方案则代表另一种完全不同的选型思路。这篇文章就围绕这两款工具做一次详细的对比解析同时分享一下我在实际部署、升级过程中踩过的坑尤其是“Docker部署的Harbor如何升级Nginx”这种高频操作希望能给正在选型或者准备搭建私有镜像仓库的同学一些参考。1. 选型前必须想清楚的三个问题1.1 制品管理工具到底在管什么很多团队一开始对制品仓库的认知就是“找个地方放镜像”这个理解太浅了。制品管理工具本质上要做三件事第一安全地存储制品文件容器镜像、Helm Chart、二进制安装包都算第二给不同角色分配不同的访问权限不能让每个开发都直接连底层存储第三记录操作审计让每一次推送、拉取、删除都有迹可循。只看“能存镜像”这个维度随便一个Nginx静态目录都能做到但一旦涉及权限隔离、镜像同步、漏洞扫描、生命周期清理就必须上一个正经的制品管理工具。1.2 团队规模和资源决定了工具上限我见过不少小团队拿一两台2核4G的云主机硬跑Harbor结果把所有容器拉起来以后机器直接卡死连CICD进程都被拖垮。反过来有些几十人的研发团队为了省事用了很轻量的方案结果镜像没有权限隔离任何人改了版本号都能随便推出问题只能靠人工排查。所以选型不是“哪个工具更高级”而是“哪个工具在你的团队规模、资源预算、运维能力下能长期健康地运行”。1.3 Harbor和Hadess的核心定位差异Harbor走的是“企业级全家桶”路线默认安装就会拉起Nginx、Core、Registry、Portal、Database、Redis、JobService、Trivy等十来个容器功能非常完整但部署和运维成本也随之上升。Hadess则是典型的轻量路线尽量用最少的组件实现核心功能部署门槛低资源占用小适合对功能要求不那么极致的场景。说白了Harbor是重型港口负责吞吐量、多租户、合规安全Hadess更像一个小码头只解决“能停船、能卸货”的问题。2. Harbor企业级制品仓库的核心能力拆解2.1 Harbor的运行时架构和组件分工Harbor 2.x 的默认部署形态是十来个容器协同工作。入口是Nginx负责HTTPS终止和反向代理Core是主业务服务处理API请求、权限校验、项目逻辑Registry是镜像存储层本质上还是Docker DistributionPortal提供Web界面DatabasePostgreSQL存元数据Redis负责缓存和一些异步任务JobService处理复制、GC、扫描这些后台任务Trivy负责漏洞扫描。理解这个架构对后续运维非常重要。比如你想升级Nginx就不能只改一个容器因为入口代理后面还连着Core、Registry、Portal如果你单独把Nginx版本跳得太高可能因为HTTP协议头或者上游路径配置不兼容导致整个服务不可用。2.2 权限、复制和审计这些“企业功能”到底解决了什么问题Harbor的项目权限模型非常成熟项目-仓库-用户三层结构配合管理员、开发者、访客、受限访客等角色基本上能够覆盖一个中等规模研发团队的全部访问控制需求。它还支持机器人账号方便CICD流水线用临时令牌去拉取镜像而不是把管理员密码写在Jenkins或者GitLab的变量里。镜像复制是Harbor另一个杀手级功能。比如主集群在上海、灾备集群在北京你只需要配置一条复制规则Harbor会自动把指定项目的镜像增量同步过去。我实际用下来这个功能对于多机房部署、业务迁移非常省心比写脚本调用docker pull/push再手动管理一致性要可靠很多。审计日志同样重要。合规要求下谁在什么时间删除了哪个镜像、谁修改了项目成员权限都必须可以追溯。Harbor的日志一方面落在系统日志里另一方面在页面上也能看到操作记录。Hadess这种轻量方案在这方面基本是空白选型时要注意。2.3 磁盘规划和目录结构解析用Docker部署Harbor时harbor.yml里的data_volume配置决定所有持久化数据存在哪里我一般会单独挂一块数据盘比如/data/harbor。这个目录下有几个子目录需要格外注意registry目录存的是真正的镜像层文件database目录是PostgreSQL元数据redis目录是缓存数据chartrepo目录是Helm Chart仓库。镜像层文件是典型的“只增不删”型数据。你在页面上删掉一个镜像Harbor只是删除了元数据引用底层文件还在必须手动触发垃圾回收GC才能真正释放空间。我做日常巡检时看到数据盘使用率超过80%就非常紧张因为一旦写满Registry会进入只读状态所有推送直接失败这种事故在深夜最容易发生。2.4 Harbor的版本升级心法Harbor整体升级路径比较长但从2.x开始流程已经比较成熟了。核心逻辑是先备份harbor.yml和数据库然后执行官方升级脚本它会自动迁移数据库结构并拉取新版本镜像。我在这里必须提醒一句升级前一定要看官方Release Note不同小版本可能涉及数据库不兼容变更跨多个大版本时最好先升级到中间版本再继续往上升。升级过程中如果把Nginx、Core、Portal这些组件混合升级很容易出现版本不匹配的问题。所以除非是安全补丁需要单独处理Nginx否则我建议跟着整体版本走不要单独横向升级某一个组件。3. 用Docker Compose快速搭建Harbor私有镜像仓库3.1 部署前的硬件和系统要求官方文档给出的最低配置是2核4G但我实际经验是生产环境如果承载日常研发至少4核8G起步。镜像数据盘建议单独挂载容量按“未来一年镜像增长量再乘以2”来估宁多勿少因为数据盘扩容通常要停机操作。系统环境方面建议使用较新的Ubuntu LTS或CentOS 7以上内核版本不要太老。Docker要装好Compose插件也要配好Harbor 2.x 推荐使用 docker compose 命令老版本的docker-compose命令也能用但如果Compose版本太旧启动时会出现一些莫名其妙的配置解析错误。3.2 harbor.yml关键配置项详解下载Harbor离线安装包后解压目录下会有一个harbor.yml.tmpl模板文件复制一份为harbor.yml再改。我这里给出一个常用的最小化配置示例hostname: registry.example.com http: port: 80 harbor_admin_password: YourStrongPassword database: password: YourDBPassword data_volume: /data/harbor trivy: ignore_unfixed: true jobservice: max_job_workers: 10hostname字段是核心所有客户端docker login时访问的地址必须是客户端能解析到的域名或IP不要填localhost否则其他机器没法登录。harbor_admin_password是管理员初始密码企业环境里一定要改成强密码并且后续修改需要在数据库里操作极其麻烦。database.password是数据库密码Compose编排会用它初始化PostgreSQL建议也改成独立强密码。data_volume、trivy、jobservice这几项都比较直观按需调整即可。3.3 初始化、启动和验证流程配置文件准备好以后先执行./prepare这个脚本会根据harbor.yml生成Nginx、Core等组件的实际配置模板。然后执行./install.sh它本质上就是调用docker compose up -d拉起所有服务。如果你不想用脚本直接docker compose up -d也完全可以两者差别不大。我第一次部署时犯过一个小错误直接改了harbor.yml里的端口然后以为docker compose up -d会生效结果端口没变。后来才意识到改完harbor.yml以后必须先执行./prepare重新生成配置再重启容器修改才会真正落到Nginx和Core的配置里。启动完成后访问https://your-host/用admin账号登录。如果提示证书不受信任是因为Harbor默认用的是自签名证书正常现象后续换成正式证书即可。更稳妥的验证方式是命令行检查服务健康docker compose ps curl -u admin:YourStrongPassword https://registry.example.com/api/v2.0/systeminfo返回正常的JSON信息说明Harbor本身没有问题接下来进入镜像推送和拉取的端到端测试。3.4 首次上传和拉取镜像的完整链路测试在任一台能访问Harbor的客户端机器上执行docker login registry.example.com输入管理员账号密码登录成功后再打一个测试镜像推送上去docker pull hello-world:latest docker tag hello-world:latest registry.example.com/library/hello-world:latest docker push registry.example.com/library/hello-world:latest然后到Harbor页面上看library项目下面有没有出现hello-world仓库。确认有以后再从另一台机器执行docker pull registry.example.com/library/hello-world:latest能拉下来就说明整个链路没问题了。这套测试做完建议顺手新建一个普通开发账号用这个账号在页面上做一些推送、删除操作体验一下权限控制。如果开发账号不能往library项目推镜像说明权限模型在工作你接下来只需要按照团队角色把项目和成员配好就行。4. Docker部署的Harbor如何升级Nginx4.1 Harbor里的Nginx到底是什么角色很多同学容易混淆Harbor前端的那个Nginx容器不是宿主机上装的Nginx也不是一个你可以随意替换的独立软件。它在Harbor里承担的是“统一入口”职责对外终止TLS、把/api/和/v2/的请求分别路由到Core和Registry服务同时托管Portal静态资源。官方镜像名叫goharbor/nginx-photon基于Photon OS镜像构建。理解了这层关系你就明白升级Nginx不能简单执行apt upgrade nginx也不能直接换镜像标签就算完事。因为你不仅要换Nginx二进制还要保证它与Harbor当前的Core、Portal、Registry等服务的API路由兼容。4.2 单独升级Nginx镜像的实操步骤如果只是因为Nginx版本过旧触发了安全扫描或者需要修复某个CVE可以单独升级Nginx镜像。我常用的步骤如下第一步先备份现有配置。Harbor运行时的Nginx配置在common/config/nginx/nginx.conf我一般会复制一份到nginx.conf.bak以防prepare覆盖后找不到原配置。第二步修改docker-compose.yml中nginx服务的镜像版本。比如原来用的是goharbor/nginx-photon:v2.8.4需要升级到v2.9.x直接修改image字段nginx: image: goharbor/nginx-photon:v2.9.0 restart: always volumes: - /data/harbor/common/config/nginx:/etc/nginx:z第三步执行./prepare重新生成Nginx配置。这一步实际上会用新镜像的环境变量和Harbor自身的配置模板重新生成nginx.conf确保新版本Nginx能正确解析上游。第四步执行docker compose up -d。Compose会识别到nginx镜像变化重新创建nginx容器不影响其他容器。升级完成后一定要做验证docker compose ps看容器状态再用curl -I https://registry.example.com/v2/看HTTP返回码最后实际执行一次docker login和镜像拉取。整套操作建议在低峰期做虽然Nginx容器重启一般就几秒但万一配置不兼容影响范围是全部入口流量。4.3 配合Harbor整体升级时Nginx应该怎么处理我更推荐的做法是把Nginx升级放进Harbor整体升级流程里。Harbor官方升级脚本在升级时会自动处理组件版本匹配Nginx、Core、Portal这些都会一起更新到新版本避免兼容性问题。如果你手动只升Nginx短期内可能没问题但后续做Harbor整体升级时Nginx和其他组件的版本差距可能拉大排查问题时很难判断是哪个环节出了问题。另外我踩过一个具体的坑某次我只升级了Nginx镜像然后发现页面Portal的静态资源加载缓慢后来排查发现是新版Nginx对gzip压缩和缓存静态资源的默认行为变了再执行./prepare把配置重新生成一遍才好。所以千万别图省事升级完Nginx一定要把配置模板和缓存都刷新干净。4.4 升级后验证清单升级Nginx后我一般会从四个维度检查第一服务状态docker compose ps确认nginx是Up状态第二端口监听ss -lntp检查80/443端口没有异常第三核心APIcurl -u admin:密码 https://registry.example.com/api/v2.0/systeminfo能正常返回第四镜像操作登录后实际跑一遍docker push和docker pull。这个清单看起来很简单但每一条都对应一类故障80/443端口被占会导致容器起不来API异常会导致docker login一直报错镜像操作不正常说明Nginx到Registry的路由有问题。全部通过后Nginx升级这件事才算真正结束。5. Hadess轻量制品的另一种路线5.1 Hadess是什么它和Harbor思路的不同Hadess在社区里的讨论热度不算高但它代表的轻量制品仓库路线很有参考价值。它的设计目标很明确用最低的部署成本提供制品管理最核心的能力而不是像Harbor那样提供一个庞大而完整的平台。我接触Hadess类工具的感受是它默认只跑一个容器或者一个二进制进程配置简单到像启动一个Nginx数据存储占用也比Harbor小几个数量级。如果你只是内部几个人用对权限、审计、漏洞扫描没有严格需求这种轻量方案能让你省下很多运维精力。5.2 单容器部署和日常维护Hadess这类工具的部署方式非常符合“快速私有化”的需求通常一个docker run命令就能搞定docker run -d --name hadess \ -p 5000:5000 \ -v /data/hadess:/data \ --restartalways \ your-image:tag数据目录只需要挂载一个镜像文件、元数据、日志全在这个目录下面。升级也简单拉新镜像、停掉旧容器、换挂载目录重新启动数据不丢整个过程几分钟完成。日常维护方面我建议在宿主机上配一个crontab定时清理旧镜像或者定期通过脚本调用API清理不再使用的tag。因为轻量方案通常没有内置垃圾回收机制长期运行后磁盘占用只增不减如果不管它迟早会撑满。5.3 Harbor与Hadess的详细功能对比我整理了一张表格把两款工具在不同维度上的表现横向对比方便大家在选型时直接对照对比维度HarborHadess轻量方案部署复杂度离线安装包或Docker Compose拉起10个以上容器单容器或单二进制一条命令启动资源占用至少2C4G生产建议4C8G以上1C1G即可正常使用权限模型项目、角色、机器人账号支持LDAP/OIDC简单用户或令牌细粒度权限较弱镜像复制同步内置多规则复制支持多机房同步一般没有需要外部脚本漏洞扫描内置Trivy无需集成外部扫描器审计与合规操作日志完整基本没有审计能力Web界面功能丰富可管理项目、成员、回收站界面简单功能有限扩展能力支持Webhook、API丰富、插件机制API简单扩展能力有限升级维护成本组件多升级链路较长简单替换镜像即可5.4 什么场景下才应该考虑轻量方案我的建议是只有满足这几个条件时才认真考虑Hadess这类轻量方案团队规模在十人以内制品类型以容器镜像为主且没有复杂的生命周期管理需求机器资源紧张连2C4G的内存都挤不出来没有外部审计合规压力纯粹为了给内部开发提供一个集中存储。反过来如果你的镜像服务要面向对外生产环境、需要覆盖多团队多项目的权限隔离、有漏洞扫描和审计合规要求或者你根本不想在半夜被“镜像推不进去”的电话吵醒直接选Harbor不要犹豫。工具轻省的是资源重的是你后续为稳定性付出的代价。6. 选型决策建议与常见问题排查实录6.1 一张表帮你快速做选型决策结合我这些年帮团队选型踩坑的经验整理一个快速判断标准关键问题适合选择制品仓库要承载生产环境核心发布流程吗Harbor团队有十人以上且分多个项目组Harbor有境外或跨地域多机房架构镜像需要同步Harbor金融、政务等要求审计合规的行业背景Harbor团队5人内自研内部项目不需要对外提供镜像服务轻量方案机器只有1C2G跑Harbor会拖垮其他服务轻量方案只是临时搭建一个镜像中转站做测试轻量方案选型的时候我建议把运维人力也算进成本。Harbor部署一次大概半天后续升级、日志清理、磁盘扩容、证书续期都有固定周期Hadess这边基本是“装上就忘”但一旦出现问题排查手段也比较有限。6.2 Harbor部署和运行中的常见问题速查表从我的实际操作经验出发以下这些问题出现的频率最高按出现概率排序现象可能原因解决方案docker compose up后80/443端口冲突容器一直重启宿主机已有Nginx或Web服务占用端口修改harbor.yml中的http/port重新prepare再启动docker login失败提示证书不可信使用了Harbor自签证书客户端配置insecure-registries或信任Harbor根证书docker push报no basic auth credentials推送前没有登录先docker login registry.example.com再push页面能访问但API请求偶发401系统时间不同步导致token校验失败配置NTP时间同步重启Harbor容器磁盘写满后镜像推不上去Registry进入只读状态清理旧镜像、触发GC、扩容数据盘GC跑完磁盘没有释放多少空间仍有其他tag引用镜像层删除无用tag后重新执行GC修改harbor.yml后不生效没有重新执行prepare执行./prepare后再docker compose up -d这张表看起来简单但每一条都是真实故障场景的浓缩。尤其是系统时间不同步平时不觉得有问题一旦token过期时间判断错乱整个集群的镜像拉取都会变得时好时坏排查起来非常痛苦。6.3 关于Hadess和轻量方案的使用提醒如果你已经决定用Hadess或同类方案我建议至少主动做三件事第一数据目录单独挂一块数据盘不要和系统盘混在一起第二写一个脚本定期清理无用的tag和镜像层别指望它自动帮你回收第三把HTTPS提前配上哪怕内部环境也要用否则镜像在网络上裸奔和把代码库密码放在明文文件里没有区别。我在实际使用中还有一个习惯就是每天晚上把制品仓库的日志收走统一汇总到日志平台里去。这样即使轻量方案本身没有审计能力至少你还能通过访问日志回溯谁在什么时间做了什么操作。6.4 我个人对制品管理选型的一些体会制品管理工具这个东西只有等到出了问题才会觉得它重要。我在早期就吃过一次大亏在一个1C2G的小机器上硬跑Harbor结果每天半夜CICD一跑容器就集体重启最后整个研发流程都被拖到白天才恢复。后来我把那台机器改成轻量方案Harbor挪到一台4C8G的专用机器上整个世界才算安静了。所以做选型的时候不要只看官网的功能列表有多长更要看自己的团队有多少人、有多少机器、有多少精力去维护。Harbor很强但它是给有准备的团队用的Hadess这类轻量方案虽然不起眼却能在资源紧张的时候真正救你一命。选型没有绝对的对错想清楚自己的边界在哪里答案自然就出来了。