☰
Harbor私有镜像仓库部署全攻略:从环境准备到生产实践
2026/10/21 12:22:46 网站建设 项目流程

作为干了几年容器化落地的人,我越来越觉得私有镜像仓库是刚需。公网仓库拉取镜像慢是一回事,更关键的是代码资产安全、版本管控和离线交付,这些都绕不开一个自建的Registry。以前大家常用官方Registry,但那个东西功能太简陋,管理界面没有、权限控制弱、还能被随意删除镜像,稍微正式一点的团队根本没法用。后来我换成了Harbor,一下踏实多了。今天这篇就从头到尾拆解一遍Harbor私有仓库的搭建流程,包括网络规划、HTTPS配置、存储后端选型、日常运维和常见坑。

1. Harbor到底是什么、为什么需要它

Harbor是某开源社区推出的云原生制品仓库项目,核心功能就是管理Docker镜像,同时也支持OCI制品、Helm Chart等。它和官方Registry最大的区别在于,Harbor自带一套完整的企业级功能:基于角色的访问控制、镜像签名与漏洞扫描、异地复制、垃圾回收、审计日志,还有一套相对友好的Web界面。真实场景中,你不需要每个人都去命令行敲Docker命令翻镜像列表,给开发、测试、运维分配不同权限,让QA只能拉取不能推送,让运维能管理项目配额,这些Harbor都能做到。

我为什么坚持用Harbor而不是直接用官方Registry加一套脚本去管理?因为省心。一开始我也写过几个Python脚本调Registry API做镜像清理,后来发现根本管不住。API文档不够完善、用户管理要做二次开发、审计日志要自己落库、并发删除还会把存储搞得乱七八糟。换到Harbor之后,这些能力基本都内置了,配置项可以持久化,Webhook能对接飞书或邮件告警,出了问题也容易排查。

从适用场景来看,Harbor适合以下情况:团队超过五个人且共用镜像仓库;有镜像版本回溯或安全审计的需求;需要离线部署和跨机房同步;希望把制品管理和CI/CD流水线做联动。你如果只是自己开发玩,机器上装个Docker Registry也够用,但凡是正经交付项目,建议直接上Harbor。它带来的管理收益远大于那点部署成本。

Harbor本身的架构并不复杂。核心组件包括核心服务、数据库(PostgreSQL)、缓存(Redis)、注册表适配层(registry)、Portal前端、JobService(负责复制、扫描等异步任务),以及可选的Trivy扫描器等。我推荐至少用一台4核8G的机器去部署,磁盘单独一块,用来放镜像数据。

2. 部署前要考虑清楚的事

2.1 网络规划与端口选择

Harbor默认监听80端口,但你要是想走HTTPS,就要把443端口留出来。我建议在一开始就规划好访问域名和IP,不要后面再改配置,因为Harbor的访问地址会和镜像仓库地址绑定,一旦推送镜像时写了域名,后面换域名或IP,所有客户端都要改配置,麻烦得很。

我自己习惯用宿主机IP加端口方式来访问,比如registry.example.internal:8443。这种用法在测试环境没毛病,但生产环境还是建议用域名加反向代理。Harbor前面对一个Nginx,把443转发到Harbor的8443端口,证书统一放在Nginx层管理。你要是让Harbor自己处理证书也完全可以,就是后续证书轮换时要多操作Harbor的配置重启。

网络规划还要考虑机房防火墙和跨网段访问。很多公司企业内部有多个网段,开发网、测试网、生产网是隔离的,你要提前确认需要访问Harbor的网段都放通了,端口方面TCP的80、443是基础,如果开了复制功能还得看各机房之间能不能互通。另外提醒一句,Harbor和K8s集群的交互流量不低,尽量别把仓库放在跨公网的链路上,否则拉取镜像延迟会高得离谱。

2.2 存储后端的选型

Harbor的镜像数据默认存放在宿主机的/data/docker/registry目录下(具体看data_volume配置)。这块存储怎么选,直接影响仓库的可靠性和可用性。单机环境我直接挂一块独立的云盘或物理磁盘,不做任何叠加层,最稳。如果你用NFS或Ceph网络存储,要特别留意I/O延迟和锁冲突,多个Harbor实例共享同一份存储时,在某些并发写场景下会出现目录互操作异常。

大文件在分布式存储上的性能表现往往不如本地盘,尤其是镜像层多且大时。如果能接受单点风险,本地磁盘是最省心的选择。如果非要高可用,我更建议做双Harbor实例加主从复制,而不是两个实例挂同一份共享存储。主从复制写起来简单、逻辑清晰,还能顺便做跨机房灾备。

数据库方面,Harbor默认使用PostgreSQL,数据放在/data/database目录。小规模使用不需要怎么操心,但如果镜像量和用户量大,建议定期备份这个目录,或者干脆把数据库外置到托管数据库服务上。镜像元数据丢了还能通过重新推送恢复,但用户权限、项目配置、复制规则丢了,重新配置一遍够你喝一壶的。

2.3 版本选择与兼容性

Harbor的各个版本差异不小,安装前一定先看Release Notes。比如较新的版本会调整配置项名称、默认启用Trivy扫描、改变Harbor.yml的结构,你要是直接拿旧教程的配置去填,部署时有可能报错。

提醒一个最容易翻车的点:老版本Harbor使用的docker-compose文件版本和新版本不一定兼容。有时候升级Harbor之后,依赖的镜像tag变了,但docker-compose文件没对,导致起不来。建议部署前看清楚Harbor对应要求的最低Docker和Docker Compose版本。我这里建议Docker 20.10以上,Docker Compose 2.x以上。Docker Compose 1.x也不能说完全不行,但功能上差一些,且新版Harbor的compose文件语法它可能不认识。

另外提醒一点:某些Linux发行版自带的docker-compose是很老的版本,比如Ubuntu 20.04自带的1.25,Harbor要求2.0以上,直接装可能遇到Compose文件格式解析失败。这里统一推荐单独安装docker-compose-plugin或者直接用docker compose子命令。

3. 环境准备:把地基打好

Harbor本体依赖Docker和Docker Compose,这部分环境如果没弄好,后面全是坑。先说我的实际操作环境:一台私有的CentOS 7.9虚拟机,4C8G,一块200G数据盘挂在/data,系统盘和数据盘分开,避免镜像数据把系统盘撑爆。

安装基础工具链时,我习惯先换好系统源再装软件包。CentOS上修改/etc/yum.repos.d/下的源文件,Ubuntu则是/etc/apt/sources.list。这一步不用多说,但现实是很多人的安装卡在拉取依赖包阶段,花在等下载的工夫比部署本身还长。如果公司有内网源,直接用内网源,那才是最快的。

Docker安装我走官方脚本或包管理器都试过。建议保留包管理器方式,方便后续指定版本升级:

# CentOS yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io systemctl enable --now docker

安装完确认一下版本:

docker --version docker compose version

我碰到过装了docker-ce后没有docker compose子命令的情况,因为新版Docker把Compose拆成了独立插件。你需要单独装docker-compose-plugin:

yum install -y docker-compose-plugin

Docker配置方面,有几个参数建议改一下。第一是>{ "data-root": "/data/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "5" }, "registry-mirrors": ["https://docker.mirrors.internal"] }

注意:registry-mirrors是给docker pull用的公共镜像加速配置,和Harbor推送无关。你要是公司有内网镜像代理,填内网地址;没有的话,可以留空或填可用的公网加速地址。

改完配置重启Docker:

systemctl daemon-reload systemctl restart docker

验证一下Docker能正常跑:

docker run hello-world

拉不下来hello-world也不用慌,本地docker version能正常显示Client和Server就行。另外,千万别忘了检查时间同步。容器镜像的tag验证和日志审计都依赖时间,机器时间飘了,轻则证书校验失败,重则Garbage Collection把还在用的镜像层清了。装好chrony或者ntpdate,保持和NTP服务器同步。

4. Harbor安装包下载与配置文件修改

4.1 选择合适的安装包

到Harbor的GitHub Release页面下载对应版本的离线安装包。在线安装包体积小一些,但安装时还要从公网拉取大量镜像,离线包更省事。我一般直接选离线包,例如harbor-offline-installer-v2.11.0.tgz。下载完先校验SHA256,避免文件损坏或下载不完整。

解压之后会得到一个harbor/目录,里面有install.sh、harbor.yml.tmpl、common.sh和一堆预打包的镜像tar包。部署Harbor必要的内容基本都在这里,不要手动去删解压出来的tar文件,install.sh脚本在加载镜像时需要找到它们。

4.2 harbor.yml关键配置项解读

先复制模板:

cp harbor/harbor.yml.tmpl harbor/harbor.yml

然后逐项修改。重点配置项我列一个表说清楚:

配置项作用我常用的值注意点
hostname仓库访问地址内网域名或IP客户端要能解析或直接访问到
http.portHTTP端口80要改的话同时注意端口占用
https.portHTTPS端口443如果走TLS,证书路径要配好
harbor_admin_password管理员初始密码强随机字符串至少要12位,部署完尽快改
data_volume镜像数据目录/data/harbor确保目录存在且空间足够
database.password数据库密码强随机字符串不要用默认值,安全第一
trivy.enabled漏洞扫描开关true开启后占资源,但安全收益大

hostname这一项,不是随便填一个域名就完事。客户端机器上配置Docker仓库时,依赖hostname做TLS证书校验和仓库识别。万一hostname写成了IP,后续想换域名,就得重新生成证书、改配置、重启Harbor,所有镜像tag里的仓库地址可能也要跟着改。建议一开始就定一个稳定的内网域名。

harbor_admin_password和database.password这两处如果不修改,Harbor启动后会生成随机密码并打印到日志里,可它只出现一次,你要是错过了还得重置,反而更麻烦。稳妥做法:在harbor.yml里直接写死强密码,部署完成后存到密码管理库里。

data_volume强烈建议换成独立数据盘的路径,不要在/根目录下。镜像文件占磁盘空间是逐渐涨的,一旦把根分区写满,系统直接卡死,那真是欲哭无泪。先创建目录:

mkdir -p /data/harbor

检查磁盘空间:

df -h /data

4.3 HTTPS证书配置

生产环境一定要开启HTTPS。Docker客户端和Harbor之间的通信如果走明文HTTP,镜像内容在网络上裸奔,这个风险太高了,无论从安全合规还是从数据完整性的角度都不能接受。

如果你的域名通过正式CA签发证书,直接把fullchain和私钥填进去就行。自己内部用的,更多是自签证书。我来走一遍完整的自签证书生成流程。

先生成CA私钥和证书:

mkdir -p /data/certs && cd /data/certs openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -sha256 -days 3650 \ -subj "/CN=Harbor Internal CA" \ -key ca.key -out ca.crt

生成仓库域名私钥:

openssl genrsa -out harbor.key 2048

创建证书签名请求配置文件。这里要注意把域名和IP都写进subjectAltName,否则客户端通过IP访问时TLS校验会失败:

cat > harbor.csr.cnf <<'EOF' [ req ] distinguished_name = dn req_extensions = ext prompt = no [ dn ] CN = registry.example.internal [ ext ] subjectAltName = @alt_names [ alt_names ] DNS.1 = registry.example.internal IP.1 = 192.168.10.20 EOF

生成CSR并签发证书:

openssl req -new -key harbor.key -out harbor.csr -config harbor.csr.cnf openssl x509 -req -in harbor.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -out harbor.crt -days 825 -sha256 -extensions ext -extfile harbor.csr.cnf

将证书和私钥放到Harbor能读取的位置,并在harbor.yml中配置:

https: port: 443 certificate: /data/certs/harbor.crt private_key: /data/certs/harbor.key

提示:自签CA的情况下,每个需要访问Harbor的客户端机器,都要把ca.crt加到Docker的信任列表里。路径一般是/etc/docker/certs.d/<hostname>/ca.crt。这一步漏了,直接后果就是pull/push时报x509 certificate signed by unknown authority。

5. 安装启动Harbor

5.1 执行安装脚本

配置改完后,运行安装脚本:

cd /path/to/harbor ./install.sh --with-trivy

--with-trivy就是开启漏洞扫描功能。如果不需要扫描,可以不加这个参数,能省不少内存。Trivy扫描器在Harbor中是按需启动的,真正扫码时才会跑大量任务,平时处于待命状态,所以也不用太担心空占资源。

install.sh会做这几件事:首先加载离线包中的镜像tar包到Docker中;然后根据harbor.yml生成docker-compose.yml;最后通过docker compose把Harbor的各个组件拉起来。整个过程中,如果看到✔ ----Harbor has been installed and started successfully----,说明成功了。

5.2 验证Harbor各组件状态

安装完成后,用docker compose查看服务状态:

cd /path/to/harbor docker compose ps

正常情况下,你会看到这些容器处于运行状态:

容器名职责
harbor-core核心业务逻辑,API处理
harbor-dbPostgreSQL数据库
harbor-jobservice异步任务(复制、GC等)
harbor-portalWeb前端
harbor-redis缓存
harbor-registry镜像存储与上传下载
harbor-trivy漏洞扫描器
nginx入口反向代理

有一个非常容易踩的坑:Harbor容器全都起来了,但浏览器访问页面是502。这种基本都是Harbor内部网络组件启动顺序问题,或者磁盘空间不够导致某些容器启动失败。先看nginx容器日志,再看harbor-core日志,基本就能定位。

5.3 浏览器与Docker客户端联通测试

浏览器访问https://registry.example.internal,用admin账号和harbor_admin_password登录。第一次登录之后,我建议立刻创建一个普通管理员或开发者账号,日常业务别用admin,减少误操作风险。

Docker客户端配置信任自签证书。每台客户端机器上执行:

mkdir -p /etc/docker/certs.d/registry.example.internal cp /data/certs/ca.crt /etc/docker/certs.d/registry.example.internal/ca.crt systemctl restart docker

不要直接往/etc/docker/certs.d/丢Harbor的证书,要放在以hostname命名的子目录下。Docker找证书的逻辑就是按hostname匹配目录,目录名不对照样不认。

登录Harbor:

docker login registry.example.internal

输入用户名密码,显示Login Succeeded就通了。接下来打一个标签推送测试:

docker tag nginx:latest registry.example.internal/library/nginx:1.25 docker push registry.example.internal/library/nginx:1.25

登录Web界面,到library项目下就能看到这个nginx镜像。这一套通了,说明Harbor部署基本没问题。

6. 配置与运维的一些实际操作

6.1 镜像复制规则和跨机房同步

在Web界面的“复制管理”里可以创建复制规则。我配置过一个从生产Harbor复制到备份Harbor的规则,走的是内网专线,同步大量镜像时很稳定。复制方式有push和pull两种。push是源Harbor推送到目标,pull是目标从源拉取,我个人更推荐pull模式:备份端主动去拉,源端不用开启外部访问,安全上更可控。

创建复制规则时要填目标仓库的地址、用户名密码,以及同步的资源和过滤条件。比如只同步含latest标签的镜像,或者只同步nginx、redis这些基础组件,都可以写正则过滤。JobService会定期执行这些复制任务,即使某次失败,也会有重试和日志记录。

6.2 垃圾回收(GC)

镜像被删除后,底层的镜像层不会立即清除,需要手动触发垃圾回收。Harbor的GC功能在“系统管理 -> 垃圾回收”里。执行GC前注意,它会暂时停止对某些镜像清单的引用操作,如果此刻正在拉取大镜像,理论上可能报错。我一般选择在凌晨低峰期执行。

GC完成后,查看磁盘空间是否释放:

df -h /data/harbor

6.3 镜像漏洞扫描

开启Trivy扫描后,你可以在项目的“扫描”标签下手动触发扫描,也可以设置策略让Harbor在镜像推送后自动扫描。自动扫描的配置在项目设置里,在Automatically scan images on push前打勾。扫描结果会标记漏洞等级,包括严重、高危、中危、低危,并展示漏洞详情和CVE编号。

实际体验中,Trivy的扫描比较快,但首次扫描大镜像时需要拉取漏洞数据库,耗时会偏长。如果离线环境无法更新漏洞库,扫描效果会大打折扣,这一点要心中有数。有安全合规要求的话,漏洞库的离线同步机制务必提前搭建。

6.4 用户、项目与权限管理

Harbor的项目分为公开和私有两种。公开项目任何人登录后都可以拉取镜像,适合存放基础镜像或公共制品;私有项目只允许被授权用户访问。生产环境我基本都用私有项目,按团队划分权限。

权限模型里有几个角色:项目管理员、开发者、访客,以及系统级别的管理员。开发者可以推送镜像,访客只能拉取,项目管理员还能管理成员和策略。我通常把CI/CD机器要使用的账号配成开发者,只赋予指定项目的权限,避免它获取整个Harbor的管理权限。

有一个细节:Harbor3.0以后新增了机器人账号,专门给CI/CD系统使用。机器人账号没有密码交互,用令牌方式认证,可以做成自动定期轮换,权限隔离做得好,审计日志也干净。如果还在用普通账号挂到CI系统里,建议尽快迁移到机器人账号。

7. 常见问题和故障排查实录

7.1 镜像push时报x509证书错误

这个问题八成是Docker客户端不信任你的自签CA。检查几处:

ls /etc/docker/certs.d/registry.example.internal/

目录里必须有ca.crt,而且这个文件得是CA证书本身,不是Harbor的服务器证书。确认无误后重启Docker:

systemctl restart docker

再次执行docker login测试。还有一种少见情况:某些Docker版本会用系统CA库忽略/etc/docker/certs.d下的配置。这时把ca.crt也拷贝到系统CA目录下:

cp /data/certs/ca.crt /usr/local/share/ca-certificates/harbor-ca.crt update-ca-certificates

7.2 端口被占用导致启动失败

harbor.yml里http.port和https.port如果有冲突,nginx容器会起不来。优先排查占用情况:

netstat -tlnp | grep -E '80|443'

如果80端口已经被其他服务占了,你可以只启用HTTPS,把http.port注释掉,或改到别的端口。注意DNS、防火墙都要同步调整。

7.3 磁盘空间不足导致Harbor服务假死

这个坑我踩过不止一次。Harbor依赖的组件多,日志文件也多,如果/和/data的分区都达到90%以上,容器时不时就会OOM或无响应。先快速定位:

df -h

再看哪些目录吃空间:

du -sh /data/harbor/* | sort -rh | head

清理大文件后,记得顺手清理Docker日志。日志文件路径通常是/var/lib/docker/containers/<container_id>/*-json.log,被日志撑爆的场景我见过太多了。如果已经设置了log-opts参数轮转,就不用太担心。

7.4 删除镜像后磁盘空间没释放

Harbor的机制是镜像被delete后,需要GC才能真正删除存储层。去系统管理页签开启并执行垃圾回收。如果你用的是分布式存储,GC是在线执行的,但数据层的碎片回收依赖底层存储的实现,有时确实需要等一会儿。

7.5 Harbor升级时的坑

升级前先备份harbor.yml和/data/database目录。用新版离线包覆盖旧版时,install.sh会自动做数据库迁移,但迁移失败也有概率。我后来都是先用一台测试机跑一遍升级流程,确认无异常再上生产,这个经验特别重要,不想线上翻车就别省这一步。

7.6 内网DNS解析导致docker login超时

有些机器能访问HarborIP,但docker login非常慢。我先用手动解析测试:

curl -v https://registry.example.internal/v2/

如果curl很慢,检查/etc/resolv.conf中的DNS配置,或者为Harbor域名指定本地DNS记录。实在不行就加--add-host参数临时绕过,但生产环境还是得把DNS配好。

8. 一点个人实操总结

Harbor部署本身不复杂,真正花时间的是前期规划:存储放哪、证书怎么发、权限怎么设、备份怎么做。这些事如果在安装之前想清楚,后面会非常省心;反过来,要是装完再改,每一次变更都牵动一堆客户端配置。

我后来在实际项目里直接把Harbor配合K8s使用,每个命名空间对应Harbor里的一个项目,通过imagePullSecret来认证。这样跨团队协作时权限边界很清晰,哪个团队只能拉取自己项目的镜像,一目了然。再配合Webhook通知到内部IM,推送镜像时很快就能反馈到团队群里。

如果你正在从零开始搭Harbor,建议先按本地虚拟机走一遍完整流程,了解安装脚本、目录结构和配置项背后的关系,然后一次到位部署到生产机器。不要一上来就加一堆高级功能,先把基础走通,再逐项开启复制、扫描、配额这些能力,出问题时排查面会小很多。

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

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

立即咨询