Harbor私有仓库从部署到运维全攻略:解决镜像存储与分发难题
2026/9/16 4:39:03 网站建设 项目流程

如果你已经在自己机器上跑过一阵子Docker,迟早会遇到同一个问题:镜像打好包之后,到底往哪儿放。扔到公共镜像仓库,拉取频次经常被卡脖子,涉及内部配置的镜像放在公网上心里也不踏实;多台服务器之间来回传tar包,传一次两次还能忍,传多了就想骂人。我的答案是自建一套Harbor私有仓库。Harbor是目前用得最广的企业级容器镜像仓库,部署不复杂,资源开销也不算离谱,但功能比Docker官方Registry完整太多。这篇是Docker系列第五篇,前面把安装、常用命令、数据卷和Compose都聊过了,今天专门讲Harbor从部署到日常管理的完整链路。

1. 从“镜像没处放”说起:Harbor到底解决了什么问题

1.1 公共镜像仓库用着用着就不香了

很多团队最开始用Docker Hub,图的是省事,pull镜像直接写名字就行。但用得稍微频繁一点,痛点就全出来了。首先是限流,匿名用户拉取镜像有次数限制,一旦你们CI流水线里频繁构建、频繁拉同一批基础镜像,很容易就触发429,构建突然失败,查了半天发现是拉镜像被拒了,非常窝火。其次是速度,公共仓库服务在国外,几G的系统镜像,运气不好能拉半小时,团队里每个人都卡在下载上,时间就这么白白烧掉。

还有安全合规层面的问题。公司内部项目组之间的镜像,往往带着业务代码、配置文件、数据库连接信息,这些东西放到公共仓库上,从合规角度看风险太大。尤其做过政企项目的朋友应该懂,甲方连私有化交付环境中所有组件的出处都要审计,镜像如果从公网来,交付材料根本没办法写。

这还只是使用层面的问题。更隐蔽的威胁是供应链安全,公共仓库里的镜像鱼龙混杂,你永远不知道某个热门镜像的维护者是谁、里面被塞了什么东西。2024年曝光过不少恶意镜像投毒事件,就是有人在公共仓库里上传名字碰瓷常见镜像的坏东西。这种事,小团队踩一次就够喝一壶。

1.2 原生Registry太素,Harbor补全了哪些能力

有人说,不想用公共仓库,那我用Docker官方提供的registry:2镜像自己搭一个不行吗?技术上当然行,Docker官方Registry确实是最轻量的私有仓库方案,一条docker run就能起一个。但你要想清楚,裸Registry只是存储和分发,其余能力基本等于零。

我用一张表把两者做个对比,你就能直观看到差异:

能力Docker官方RegistryHarbor
镜像存储与分发
Web管理界面有,中文支持好
多项目隔离有,项目级别权限
用户/角色管理有,RBAC权限模型
镜像漏洞扫描有,基于Trivy
复制同步有,跨实例同步
垃圾回收手动API触发UI一键触发
审计日志有操作日志
机器人账号有,适合CI/CD

所以说白了,Registry只解决“有没有仓库”的问题,Harbor解决的是“仓库好不好用”的问题。尤其当你需要多人协作、按项目分权限、镜像签名、字段扫描这些能力时,Harbor几乎是中小团队性价比最高的选择。它最初由VMware团队开源,后来捐献给了CNCF,生态成熟度很高,国内社区文档也非常丰富,遇到问题基本都能搜到答案。

1.3 什么样的情况下,Harbor是最优解

我自己的判断标准很简单:只要你不满足于“能push能pull”,而是想让镜像仓库成为团队基础设施的一部分,那就可以上Harbor。最典型的三类场景:

  • 内网开发环境:团队内网服务器无法直接访问公共仓库,或者访问速度很慢,把基础镜像提前打好放进Harbor,所有机器从内网拉取,速度提升是肉眼可见的。
  • CI/CD流水线:Jenkins、GitLab CI、GitHub Actions这类流水线,构建产物是镜像的话,需要一个稳定、可限权、支持机器人账号的仓库,Harbor的Robot Account机制就是为此设计的。
  • 多环境交付:开发环境、测试环境、生产环境都要部署同一套镜像,用Harbor复制规则可以自动同步,省去手工搬运。

这里插一句,别一听Harbor就想着上Kubernetes、搞高可用。绝大多数中小团队,一台4C8G的物理机或者云主机,装一个单机版Harbor,就已经能顶住每天几十上百次的构建推送了。真正的瓶颈通常在存储和磁盘IO,而不是Harbor这个进程本身。

2. 动手前先定三件事:域名、证书、安装包

2.1 域名怎么定,决定了后面三年轻松还是折腾

很多人第一次装Harbor,图省事直接用IP访问,比如192.168.1.100。我强烈不建议这么干。Harbor默认走HTTPS,而Docker客户端在访问HTTPS仓库时,会严格校验TLS证书校验,证书里面的域名必须和你访问的地址一致。如果你用IP访问,证书要么绑IP,要么就得给Docker配置insecure-registries跳过校验,往后每加一台客户端机器,都要去改一遍Docker配置,烦到你怀疑人生。

正确做法是一开始就规划一个专用域名。内网环境我习惯用registry.example.local这种,和公网域名区分开;如果有独立公网域名,也可以用registry.example.com。域名通过内网DNS解析到Harbor所在机器即可,将来要换机器、做负载均衡、配置复制规则,这个域名都不会变,比IP稳得多。

域名定下来之后,所有Docker客户端的指向都变成了docker login registry.example.local,语义清晰,配置文件里也不用写乱七八糟的IP加端口。

2.2 HTTPS证书:自签、内网CA还是公网证书

HTTPS证书是Harbor部署中最大的一个坑,没有之一。安装脚本对证书的要求非常死板:如果harbor.yml里配置了https,那么certificateprivate_key指向的文件必须存在,而且必须是合法文件,否则直接报config validation错误。

我实际用过三种方案:

  • 自签CA:用OpenSSL生成一个自建CA,再用这个CA签发Harbor证书,然后把CA证书分发到所有需要登录Harbor的机器上。这是最推荐的内部方案,既能用HTTPS加密传输,又能保证Docker客户端校验通过。初始化工作量略大,但一劳永逸。
  • 公网CA:如果你的Harbor域名有公网解析,直接上Let's Encrypt免费证书,一切校验都省了。但内网环境一般不适合。
  • 纯HTTP:测试环境图省事,也可以不开HTTPS,只用80端口。但这意味着镜像明文传输,生产环境我肯定不会这么干。

自签证书生成过程可以简单写成这样:

# 生成CA私钥和证书 openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -subj "/CN=Harbor CA" -out ca.crt # 用CA签发Harbor服务器证书 openssl genrsa -out server.key 4096 openssl req -new -key server.key -subj "/CN=registry.example.local" -out server.csr echo "subjectAltName=DNS:registry.example.local" > ext.cnf openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile ext.cnf

把生成的server.crtserver.key放到一个固定位置,比如/data/cert/,后面配置harbor.yml的时候要用到。

2.3 在线包还是离线包,以及机器资源怎么给

Harbor的release页面提供两种安装包:在线安装包和离线安装包。差别就在安装过程中要不要从公网拉镜像。

在线安装包很小,执行install.sh时会动态从Docker Hub拉取Harbor各组件镜像。听起来方便,但你想想,如果服务器连公网都不顺畅,装到一半拉取失败,那才叫欲哭无泪。所以只要条件允许,一律建议用离线安装包。离线包体积大概在1GB左右,里面把Harbor所有组件镜像都打包好了,安装过程不依赖公网,内网环境也能一次成功。

机器资源方面,Harbor默认会拉起11个左右的容器,包括Nginx、Registry、Core、JobService、PostgreSQL、Redis、Portal,如果启用了Trivy漏洞扫描,还会多一个Trivy容器和一个数据库导入任务。我的建议配置如下:

场景CPU内存磁盘
学习/测试2核4GB50GB
中小团队生产4核8GB200GB+
并发高/大量镜像8核+16GB+500GB,建议分离存储

这里特别提醒一句:Harbor的数据目录一定要放在磁盘空间充足的分区上,不要和系统盘抢空间。镜像这东西增长起来非常快,一个镜像动辄几百MB,几个项目跑下来几十GB就没了。

3. 离线包部署Harbor的完整过程与配置解读

3.1 下载离线包并校验,别用了解压才发现包是坏的

以写这篇时的2.x版本为参考,部署步骤基本一致。先去Harbor的GitHub Releases页面找到harbor-offline-installer-v2.11.x.tgz这个文件下载。服务器上没有浏览器的话,用wget直接拉:

cd /opt wget https://github.com/goharbor/harbor/releases/download/v2.11.1/harbor-offline-installer-v2.11.1.tgz

下载完成后,第一件事是校验文件完整性。官方页面会给出对应的SHA-256哈希值,用工具对比一下,确认包没损坏、没被篡改:

shasum -a 256 harbor-offline-installer-v2.11.1.tgz

我见过有人跳过这一步,结果解压出来的安装包脚本是坏的,折腾半天还以为是配置问题。校验只要几十秒,能帮你省下后面所有的排障时间。

解压并进入目录:

tar -zxf harbor-offline-installer-v2.11.1.tgz cd harbor

解压后里面主要包含harbor.yml.tmplinstall.shcommon.shprepare等文件。harbor.yml.tmpl是配置模板,我们要把它复制一份,改成自己的配置:

cp harbor.yml.tmpl harbor.yml

3.2 harbor.yml 里那些不可忽略的配置项

Harbor的配置文件是YAML格式,核心配置项不算多,但每个都很关键。我只挑最容易出错、影响最大的几个讲。

hostname: registry.example.local http: port: 80 https: port: 443 certificate: /data/cert/server.crt private_key: /data/cert/server.key harbor_admin_password: HisVeryStrongPassword123 database: password: rootpass123 data_volume: /data/harbor

hostname这里有个高频坑:这个字段不要写http://或者https://前缀,只写域名或IP本身。很多人从教程里复制,带上协议头,后面跑prepare的时候直接报错。

http.porthttps.port默认是80和443,如果宿主机上已经装了Nginx或者其他占用这两个端口的服务,改起来会很麻烦,建议提前确认端口是否空闲。我在第六节会专门讲撞端口怎么处理。

harbor_admin_password是管理员初始密码,默认值是Harbor12345。如果不改,上线第一天就有可能被扫到。安装完以后页面上也可以改,但直接在配置阶段改掉更省事。

database.password是Harbor内部PostgreSQL数据库的密码。这里多说一句,这个密码安装时会写入数据库初始化脚本,如果之后你想改,得同步改掉运行中的数据库密码和配置,很折腾。所以第一次部署的时候就设置一个健壮的密码,别用默认值。

data_volume指定数据存储目录,建议放在独立磁盘挂载点上。Harbor所有持久化数据都在这里:镜像层、数据库文件、Redis数据、日志。后面做备份和恢复,主要就是处理这个目录。

还有一个可选项external_url,如果配置了外部访问地址,Harbor会自动生成跳转URL。比较新的版本里还包含trivy的配置段,决定是否启用漏洞扫描器,后面执行install.sh时也要用对应的--with-trivy参数配合。

3.3 install.sh 执行时到底做了些什么

配置写好之后,执行安装脚本。我建议第一次装先别急着开全部组件,扫漏洞功能虽然好,但Trivy首次启动要下载漏洞数据库,机器如果配置不高,装完以后加载会很慢。基础先把核心仓库跑起来:

./install.sh

如果确实需要镜像漏洞扫描和ChartMuseum,可以加上参数:

./install.sh --with-trivy --with-chartmuseum

脚本的执行过程大致分三步:先检查宿主机Docker和Docker Compose环境,再根据harbor.yml生成docker-compose.yml和各类内部配置,最后把所有容器拉起来。用Compose管理Harbor,这是官方设计如此,也正是我们在前面文章里学Compose的意义所在——出了问题,直接docker compose ps看所有组件状态,也能用docker compose logs查单个服务的日志。

安装完成后验证容器状态:

docker compose ps

正常情况下你会看到一组容器:nginxregistryharbor-coreharbor-dbharbor-jobserviceharbor-portalredis等。如果某个容器反复重启,用以下命令排查对应日志:

docker compose logs --tail 50 harbor-core

浏览器访问https://registry.example.local,用admin和刚才设置的密码登录。登录成功后能看到主界面,左边栏有项目、日志、系统管理等菜单,说明Harbor本体已经跑起来了。

3.4 首次登录后,先做这三件事

登录进页面先别急着推镜像,我按经验做三件收尾工作。

第一,修改管理员密码。虽然harbor.yml里已经设了初始密码,页面上再改一次更稳妥,也能从管理界面确认密码策略。路径是右上角头像菜单里的“用户设置”。

第二,创建项目。Harbor里的镜像以项目为维度组织,项目名/镜像名:标签是完整的仓库地址。我习惯为每个业务系统创建一个独立项目,比如devopswebai,然后把项目的公开性设成私有,只有授权用户才能访问。

第三,配置仓库存储配额。Harbor支持项目级别的存储配额,我给每个项目设置一个上限,防止某个团队一口气把整块磁盘推满。路径是项目详情里的“配置”,可以设置仓库存储上限,比如20GB。

4. 镜像推送与客户端访问:从登录到拉取全链路

4.1 项目、用户与机器人账号:把权限分清楚

Harbor的权限模型不复杂,但很多人用起来还是习惯只用admin一个账号,大家一起push,这在小团队里没问题,团队一大就会出乱子。我建议至少做到这个程度:

  • 项目级别隔离:每个业务线一个项目,团队A不能动团队B的镜像。
  • 普通用户按角色分配:开发人员给“开发者”角色,只管推送和拉取;运维给“维护者”角色,能管理复制规则;新来的实习生给“访客”角色,只能拉取。
  • 机器人账号用于自动化:CI/CD流水线里不要用个人账号,创建机器人账号,给它一个只写或者只读的最小权限,token如果泄露,你在页面上随手吊销就能止血,不用改整个用户的密码。

机器人账号的创建入口在“系统管理-机器人账号”,或者项目详情页的“机器人账号”标签下。创建时选择权限范围,比如push-only给构建流水线,pull-only给部署流水线。生成后会得到一个token,复制保存好,页面刷新后不会再显示完整token。

4.2 Docker客户端信任Harbor的两种方式

Docker客户端默认只信任公认CA签发的HTTPS证书。如果你用的是内网CA或者自签CA,直接docker login大概率报错:

x509: certificate signed by unknown authority

要解决这个问题,有两条路。

第一条路,正规做法,把CA证书拷贝到Docker客户端的证书目录下。目录路径是有规律的,必须严格按照/etc/docker/certs.d/<harbor域名>/来组织:

mkdir -p /etc/docker/certs.d/registry.example.local cp /path/to/ca.crt /etc/docker/certs.d/registry.example.local/ systemctl restart docker docker login registry.example.local

这样Docker在访问registry.example.local时就会信任这个CA签发的证书,HTTPS加密和证书校验都正常,是最推荐的方式。

第二条路,纯测试环境的偷懒方案,在/etc/docker/daemon.json里把Harbor域名加入insecure-registries

{ "insecure-registries": ["registry.example.local"] }

改完重启Docker:

systemctl restart docker

这里面有个细节很多人会踩:如果Harbor改用了非80/443端口,比如http://registry.example.local:8080,那么insecure-registries里也要写完整,带上端口,否则Docker匹配不上,push/pull还是会失败。

4.3 一次完整的docker push/pull演练

假设项目名为devops,镜像为本地已有的nginx:1.27-alpine,推送全过程如下。

先给本地镜像打上Harbor地址的tag:

docker tag nginx:1.27-alpine registry.example.local/devops/nginx:1.27-alpine

登录Harbor:

docker login registry.example.local

输入用户名密码,或者粘贴机器人账号token作为密码。登录成功后push:

docker push registry.example.local/devops/nginx:1.27-alpine

推送过程中Docker会把镜像的各个层上传到Harbor。推送完成后打开Harbor页面的devops项目,能看到nginx这个仓库,点进去可以看每一个tag的下载次数。

另一台机器拉取镜像,就更简单了:

docker pull registry.example.local/devops/nginx:1.27-alpine

只要这台机器能解析Harbor域名,且已配置好证书信任或者insecure-registries,就能直接拉取。这里提醒一下,镜像仓库地址里项目名/镜像名:标签的路径结构是固定的,项目名必须真实存在于Harbor中,否则push时会报requested access to the resource is denied或者类似错误。

4.4 跨环境同步:复制规则是怎么帮你偷懒的

Harbor的复制规则是一个很容易被忽略但非常好用的功能。它的场景是:我有两个Harbor实例,一个在开发环境,一个在生产环境,开发环境推送了最新镜像,我想让生产环境自动同步一份。

在源Harbor的“系统管理-复制管理”里创建规则,填写目标实例的地址、用户名密码,然后设置资源过滤器,比如只复制devops/*下的镜像,触发模式选事件驱动,这样每次有新镜像是被push出来,复制任务就会自动触发,目标Harbor里马上出现对应的镜像。

复制规则的实现原理说白了就是源实例主动往目标实例推送或拉取镜像,属于仓库层面的镜像搬运。它比直接用docker pulldocker push可靠的多,因为复制任务失败时能看到详细的执行日志和重试机制,页面上一目了然。

不过我建议不要把复制规则当作严格的主备同步手段。两边的网络抖动、目标存储满、权限改动,都可能导致个别镜像复制失败。定期检查复制任务的运行状态,或者加一个巡检提醒,比指望它万无一失踏实得多。

5. 日常运维不能躲:磁盘清理、备份恢复与升级

5.1 数据目录里都有什么,删了会出什么事

Harbor的data_volume目录结构大概是这样的:

/data/harbor/ ├── database/ # PostgreSQL数据目录,保存用户、项目、规则等元数据 ├── redis/ # Redis持久化数据 ├── registry/ # 镜像数据,子目录docker/registry/v2里按层保存 ├── storage/ # 其他存储,比如扫描报告、配置导出 └── log/ # 容器运行日志

这里面最重要的就是registry/docker/registry/v2,镜像的blob层全部存在这里。很多人在服务器上看到磁盘占用高,顺手就rm -rf了觉得不正规,结果整个仓库镜像全部损坏,后悔都来不及。我的原则是:Harbor的目录,除了整目录备份和还原,永远不要手动删任何子文件。

5.2 页面删镜像不算完,垃圾回收才是真正释放空间

在Harbor页面上删除某个镜像tag,只是把镜像从仓库索引里去掉了,对应的存储层并没有被物理删除。这一点和Docker本身的镜像管理逻辑很像。真正释放磁盘空间,需要在“系统管理-垃圾回收”里创建新的回收任务。

垃圾回收的原理是扫描存储中所有镜像层的引用关系,把没有被引用到的blob做删除处理。执行回收之前,我建议先停掉正在进行的push任务,避免出现竞争条件导致回收异常。Harbor文档里也建议在维护窗口执行GC。

另外一个很多人会遇到的现象:GC任务显示执行完了,但df -h一看,磁盘空间根本没释放多少。这种情况通常是两个原因,一是确实还有镜像引用了这些层,比如你只删掉了一个tag,但同一层被另一个tag共享;二是Harbor存储目录所在的分区上,有其他大文件占着空间,可能是Docker自身容器日志,也可能是其他程序写的数据。

排查时先看Harbor数据目录占了多少:

du -sh /data/harbor/*

再看根分区整体情况:

df -h /

定位到原因再动手,别一上来就删Harbor目录,那样很可能把仓库搞崩。

5.3 备份与恢复:整目录拷贝是性价比最高的方案

Harbor的备份,最稳的方案不是单备份数据库,而是停服后整目录拷贝。Harbor运行时文件和持久化数据分布在两个地方:安装目录/opt/harbordata_volume(比如/data/harbor)。备份命令可以这样写:

cd /opt docker compose stop tar -zcf /backup/harbor_backup_$(date +%F).tar.gz /opt/harbor /data/harbor docker compose start

docker compose stop会把所有Harbor容器停止,确保落盘数据是一致的。然后对整个安装配置目录和数据目录打包,恢复的时候在同一路径下解包,重新执行一次./install.sh,它会把服务重新拉起,数据不会被初始化。

要注意的是tar打包时保留文件属主和权限,解包时用root,一般问题不大。如果恢复后容器起不来,优先检查/data/harbor下数据库目录的属主,因为当容器以普通用户身份运行时,目录权限不对会导致数据库初始化失败。这个问题坑过我好几次,你提前知道能省很多时间。

5.4 升级Harbor前,记得先看官方升级路线

Harbor升级比很多软件讲究,官方明确说了:跨大版本升级要逐级来,不能跳级。比如你当前跑的是2.8,想升到2.11,得先升2.9、再2.10、再2.11。每次升级前,备份数据目录和harbor.yml都是必须做的,官方文档里也写了升级前要执行备份。

升级过程本身不复杂,下载对应新版本的离线包,解压后把备份的harbor.yml覆盖到新版本目录,然后执行:

./upgrade.sh

脚本会自动做数据库迁移和镜像迁移。这里要特别提醒,升级前检查一下harbor.yml里有没有已废弃的配置项。Harbor每次版本更新后,有些配置字段可能改名、移除,或者新增必填项,官方release notes里都会注明。最稳妥的做法是,把新版本自带的harbor.yml.tmpl和你的旧配置diff一遍,人工确认差异后再执行升级。

我见过一个真实事故:有人在两个大版本之间跳级升级,导致数据库迁移脚本报错,最后只能从备份恢复,白忙活一晚上。所以别贪快,按路线走,安全第一。

6. 部署和运行中最常见的四个报错,我是怎么排查的

6.1 “happened in config validation”报错,三步定位到根因

热搜词里有个很典型的报错:harbor happened in config validation。这个错在跑install.sh或者prepare脚本的时候经常出现,但它的提示往往比较笼统,只告诉你配置校验失败,不告诉你具体是哪一行有问题。

我的排查方法是按顺序走三步。

第一步,检查harbor.yml本身有没有低级错误。比如hostname带没带协议头,缩进对不对,端口是不是数字,证书文件路径是否存在。YAML对缩进极其敏感,一个空格错位就会导致解析失败。

第二步,检查端口和目录。用命令确认80/443端口没被占用,同时确认证书目录和数据目录存在:

ss -lntp | grep -E ':80|:443' ls -l /data/cert/server.crt /data/cert/server.key

如果证书文件不存在,或者文件名和harbor.yml里写的不一致,config validation必报错。

第三步,用Python直接解析配置,快速定位YAML语法问题:

python3 -c "import yaml; print(yaml.safe_load(open('harbor.yml')))"

如果这一条命令输出正常的字典结构,说明YAML语法没问题,那就是某个字段值不符合Harbor的校验规则;如果报错,Python会直接告诉你是哪一行哪个位置出了问题。

这套链路走完,绝大部分config validation的报错都能定位到具体原因。

6.2 80/443端口被占用,和宿主机Nginx抢起来了

Harbor自带的Nginx容器默认监听80和443,如果宿主机上本来就有Nginx、Apache或者其他Web服务,安装后访问不了,大概率是端口冲突。

排查很简单:

ss -lntp | grep -E ':80|:443'

看到监听进程不是容器的话,有两个选择。第一个选择是停掉宿主机上的Web服务,让Harbor独占80/443。第二个选择是改Harbor的http.porthttps.port,比如改成8080和8443。

改完之后注意,以后所有Docker客户端的地址都带端口,比如docker login registry.example.local:8080,同时insecure-registries里也得写带端口的完整地址。这一点非常容易漏,因为很多人改完端口后发现页面能打开,就以为全都好了,结果客户端登录一直失败,卡半天才发现是端口没写全。

6.3 Docker Desktop虚拟化报错,是Harbor起不来的前置原因

部署Harbor的前提是宿主机Docker正常运行。如果你是在Windows开发机上用Docker Desktop做实验,启动Docker时报这个错,你其实还没到Harbor那一步:

virtualization support not detected docker desktop failed to start because virtualisation support wasn't detected

这个报错的原因,是Docker Desktop依赖硬件虚拟化,但BIOS/UEFI里没开启,或者Windows的虚拟化相关组件没装好。解决办法是先到BIOS设置里确认开启Intel VT-x或AMD-V,然后到Windows的“启用或关闭Windows功能”里,把Hyper-V和适用于Linux的Windows子系统(WSL2)都勾上,重启后再启动Docker Desktop。

如果你用的是Docker Desktop,也可以在它的设置里看“Resources”面板,确认虚拟化转发正常。这一步不搞定,后面所有Docker命令都是空谈。

6.4 磁盘写满导致push失败,GC后空间为何还没释放

运行一段时间后,镜像越推越多,磁盘可能在某次构建时突然写满。典型的故障表现是docker push执行到某个层时卡住,然后报no space left on device

我的处理流程是这样的:先看磁盘占用,确认是不是/data/harbor所在分区满了:

df -h

然后在Harbor页面里找到已经不用的镜像、tag,删掉旧的,再执行垃圾回收。但GC执行完磁盘空间并没有恢复,这是最让人疑惑的一步。

这时候不要立刻对Harbor目录动手,先去查Docker的容器日志。很多裸奔的Docker容器,默认log驱动不做限制,日志文件能撑到几个G甚至几十个G。定位大文件:

du -sh /var/lib/docker/containers/*/*-json.log | sort -rh | head -10

找到巨大的日志后,可以预留配置一下Docker的日志轮转,避免以后还出这种问题:

{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "5" } }

改完重启Docker,然后用truncate把已有的超大日志清空,磁盘空间就真的回来了。这一步排查下来,你会发现很多时候磁盘满跟Harbor关系不大,是基础环境管理不到位的问题。

我在实际管理Harbor的过程中,最深的体会是:域名和证书这块一定不要偷懒。第一套环境图省事,全用IP加HTTP,后来每加一台部署机器都要写insecure-registries配置,运维成本翻了好几倍。后来规范了域名加内网CA,所有机器只要拷一次CA证书,以后全部自动信任,省心太多。另外,建议把harbor.yml纳入版本管理,并在文件头部留注释记录每次改了什么、为什么改。Harbor升级不频繁,但隔了半年再看当初的部署配置,有一份注释真的能帮你快速回忆起当时的决策。按这套流程走下来,从零部署一个能长期稳定使用的Harbor,半天足够了。

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

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

立即咨询