1. 为什么私有化镜像仓库是团队协作的刚需
做过容器化落地的朋友大概率都经历过这样的场景:开发环境用docker pull拉公共镜像,一到生产环境就抓瞎——网络不通、拉取限速、镜像版本漂移、安全审计过不了。更别提团队里十几个开发共用一套镜像,谁改了哪个 tag、哪个版本对应哪次构建,全靠口头传递,出了问题连回滚都找不到基准点。
这就是私有镜像仓库存在的意义。它解决的核心问题有三个:镜像资产的统一存储与版本管理、内网高速分发、访问控制与安全扫描。而 Harbor 在这个赛道里,是目前企业级落地最广泛的开源方案之一。它基于 Docker Registry 做了大量增强,提供了 Web 管理界面、基于角色的访问控制、镜像复制、漏洞扫描、审计日志、垃圾回收等一整套能力。
这篇文章适合谁看?如果你正在做容器化基础设施搭建,或者团队规模到了五六个人以上、开始觉得公共仓库不够用,又或者你之前用过 Registry 但被它的“裸奔”体验劝退过,那这篇内容基本能覆盖你从零到一的全过程。我会把安装、配置、踩坑、调优这几块拆开讲,参数怎么算、为什么这么选,都给你说明白。
需要提前说明的是,Harbor 的部署方式有好几种:在线安装、离线安装、Helm Chart 部署、Operator 部署。本文聚焦在最通用、最容易复现的离线安装方式上,因为生产环境往往不允许直接访问外网,离线包能省掉大量依赖下载的麻烦。如果你用的是 Kubernetes 集群,Helm 方式会更优雅,但底层逻辑是相通的,理解了离线安装,Helm 那套你也能很快上手。
2. 部署前的整体设计与选型考量
2.1 版本选择与组件构成
Harbor 的版本迭代比较快,选版本的时候不要盲目追新。我的建议是选次新稳定版,比如当前最新是 2.11.x,那 2.10.x 就是比较稳妥的选择。原因很简单:新版本刚出来时,社区踩坑案例少,遇到问题搜不到答案;而太老的版本又可能缺少关键特性,比如某些扫描器的集成支持。
Harbor 的核心组件包括:
- Proxy:反向代理层,通常由 Nginx 或 Envoy 承担,负责流量入口和 TLS 终止
- Core:核心服务,处理 API 请求、权限校验、项目管理
- Portal:Web 管理界面
- Registry:实际存储镜像的组件,基于 Docker Distribution
- Database:默认用 PostgreSQL,存储元数据
- Redis:缓存和任务队列
- Jobservice:异步任务处理,比如镜像复制、垃圾回收
- Trivy:漏洞扫描器(2.x 版本后默认集成)
这些组件在离线安装包里都已经打包好了,你不需要单独去装。但理解它们各自的职责,对后面排查问题非常关键。比如镜像推送失败,可能是 Registry 的问题;登录报错,可能是 Core 或 Database 的问题;扫描任务卡住,那大概率要看 Jobservice 和 Trivy。
2.2 硬件与系统要求
Harbor 对资源的要求不算高,但也不能太抠。以下是我在实际项目中总结的配置基线:
| 规模 | CPU | 内存 | 磁盘 | 适用场景 |
|---|---|---|---|---|
| 测试/小团队 | 2 核 | 4 GB | 100 GB | 10 人以下,镜像量少 |
| 中等规模 | 4 核 | 8 GB | 500 GB | 30-50 人,日常构建频繁 |
| 生产级 | 8 核+ | 16 GB+ | 1 TB+ SSD | 百人以上,多项目并行 |
磁盘这块要重点说一下。镜像存储的膨胀速度往往超出预期,一个中等规模的团队,每月新增镜像层可能就有几十 GB。而且 Harbor 的垃圾回收不是自动的,需要手动触发,所以磁盘一定要留足余量。我见过太多团队一开始只给了 200 GB,三个月后就告警了。
操作系统方面,主流的 Linux 发行版都支持,内核版本建议 4.x 以上。需要特别注意的是,Docker 和 Docker Compose 的版本要匹配 Harbor 的要求。Harbor 2.10 要求 Docker 20.10+ 和 Docker Compose 2.x。如果你用的是老版本的 docker-compose(1.x),会直接报错。
2.3 网络与域名规划
Harbor 默认使用 HTTPS,这是强烈建议保持的。虽然可以配置成 HTTP,但 Docker 客户端对 HTTP 仓库需要额外配置insecure-registries,而且推送镜像时会有安全警告,生产环境不建议这么干。
域名规划上,建议用一个独立的子域名,比如harbor.internal.example.com。这里有个关键点:Harbor 的域名一旦确定,后续修改非常麻烦,因为镜像地址里会包含域名,改了域名意味着所有镜像的引用路径都要变。所以前期规划时一定要想清楚。
证书方面,如果有内部 CA,用内部 CA 签发即可;如果没有,可以用自签名证书,但需要把 CA 证书分发到所有需要访问 Harbor 的机器上。这一步很多人会漏掉,导致docker login时报x509: certificate signed by unknown authority。
3. 离线安装的完整实操流程
3.1 下载与解压安装包
首先去 Harbor 的官方发布页面下载离线安装包。文件名通常形如harbor-offline-installer-v2.10.2.tgz,大小在 500 MB 到 1 GB 之间,取决于集成的组件版本。
下载完成后,上传到目标服务器,然后解压:
tar -xzf harbor-offline-installer-v2.10.2.tgz -C /opt/ cd /opt/harbor解压后你会看到这些关键文件:
harbor.yml.tmpl:配置文件模板install.sh:安装脚本prepare:环境准备脚本common.sh:公共函数库harbor.v2.10.2.tar.gz:所有组件的镜像包
3.2 配置文件的关键参数详解
复制模板文件并重命名:
cp harbor.yml.tmpl harbor.yml然后编辑harbor.yml。这个文件是整个过程的核心,我逐段说明关键参数。
hostname:这是最重要的参数,填你的域名或 IP。如果填 IP,证书里也要包含这个 IP。
hostname: harbor.internal.example.comhttp 和 https:Harbor 2.x 默认只启用 HTTPS。如果你有证书,配置https段;如果没有,可以先用 HTTP 测试,但记得注释掉https段,否则启动会失败。
http: port: 80 https: port: 443 certificate: /your/cert/path/harbor.crt private_key: /your/cert/path/harbor.keyharbor_admin_password:管理员初始密码。建议改成强密码,虽然登录后会提示修改,但初始密码太弱会有安全风险。
harbor_admin_password: YourStrongPassword123!database:默认用内置的 PostgreSQL,密码也要改。如果你有外部数据库,可以配置外部连接,但小规模场景没必要。
database: password: YourDBPassword456! max_idle_conns: 50 max_open_conns: 100data_volume:数据存储路径。默认是/data,建议改成独立挂载的大磁盘路径,比如/data/harbor。
data_volume: /data/harbortrivy:漏洞扫描配置。默认是开启的,ignore_unfixed设为true可以忽略那些没有修复版本的漏洞,减少噪音。
trivy: ignore_unfixed: true skip_update: false insecure: falsejobservice:异步任务配置。max_job_workers控制并发任务数,默认 10,如果镜像复制任务多,可以适当调大。
jobservice: max_job_workers: 10log:日志配置。level建议设为info,排查问题时可以临时改成debug。rotate_count和rotate_size控制日志轮转,避免日志把磁盘写满。
log: level: info local: rotate_count: 50 rotate_size: 200M3.3 执行安装与验证
配置文件改好后,执行安装脚本:
./install.sh这个脚本会做几件事:检查环境、加载镜像、生成 docker-compose 文件、启动所有容器。整个过程大概需要 2-5 分钟,取决于机器性能。
安装完成后,用docker compose ps查看容器状态。正常情况下你会看到 9 个左右的容器在运行:
docker compose ps如果某个容器状态是Restarting或Exit,那就要看日志了:
docker compose logs -f <service_name>验证安装是否成功,最直接的方式是访问 Web 界面:https://harbor.internal.example.com。用admin和你设置的密码登录,能看到项目列表就说明核心服务正常了。
然后测试镜像推送。先登录:
docker login harbor.internal.example.com打标签并推送:
docker tag nginx:latest harbor.internal.example.com/library/nginx:latest docker push harbor.internal.example.com/library/nginx:latest推送成功后,在 Web 界面刷新,应该能看到library/nginx这个仓库和对应的 tag。
注意:如果
docker login报证书错误,需要把 Harbor 的 CA 证书放到/etc/docker/certs.d/harbor.internal.example.com/目录下,然后重启 Docker 服务。
4. 生产环境必须做的配置调优
4.1 存储后端的选择与配置
Harbor 默认把镜像存在本地文件系统,这对小规模场景够用,但生产环境建议用对象存储。原因有三:容量扩展方便、多节点共享存储、数据可靠性更高。
Harbor 支持 S3 兼容的对象存储、Azure Blob、GCS、Swift 等。以 S3 兼容存储为例,在harbor.yml中配置:
storage_service: s3: accesskey: your_access_key secretkey: your_secret_key region: us-west-1 bucket: harbor-images endpoint: https://s3.internal.example.com secure: true v4auth: true chunksize: 5242880 rootdirectory: /harbor这里有个坑:chunksize默认是 5 MB,如果网络带宽充足,可以调大到 10 MB 或 20 MB,能显著提升大镜像的推送速度。但也不能太大,否则单个分片上传失败重试的成本会很高。
配置对象存储后,需要重新执行./prepare和docker compose up -d让配置生效。已有的本地镜像不会自动迁移,需要手动处理或者重新推送。
4.2 垃圾回收与配额管理
Harbor 的垃圾回收(GC)是手动触发的,这一点很多人不知道。镜像删除后,实际占用的磁盘空间不会立即释放,需要执行 GC 才能回收。
GC 的操作路径是:系统管理 -> 垃圾回收 -> 立即执行。建议配置成定时任务,比如每周日凌晨执行一次。但要注意,GC 执行期间仓库会进入只读模式,所以一定要选在业务低峰期。
配额管理也很重要。Harbor 支持项目级别的存储配额,可以防止某个项目把磁盘写满。在项目设置里配置配额,比如限制每个项目最多 50 GB。超过配额后推送会被拒绝,这样能倒逼团队清理无用镜像。
4.3 高可用与备份策略
单节点 Harbor 存在单点故障风险。如果对可用性要求高,可以部署多节点集群,前面挂负载均衡。但 Harbor 的多节点部署有个前提:必须使用共享存储后端(对象存储或共享文件系统),否则各节点数据不一致。
备份策略上,需要备份的东西包括:
- 数据库:PostgreSQL 的数据,包含用户、项目、权限、镜像元数据
- 配置文件:
harbor.yml和证书 - 镜像数据:如果用的是本地存储,需要备份
/data/harbor目录;如果用对象存储,备份策略由存储层负责
数据库备份可以用pg_dump,建议每天执行一次,保留最近 7 天的备份。恢复时先停 Harbor,恢复数据库,再启动。
5. 常见问题排查与避坑经验
5.1 安装阶段的高频报错
报错一:Error response from daemon: Get https://...: x509: certificate signed by unknown authority
这是证书问题。解决方法有两种:一是把 CA 证书放到 Docker 的信任目录,二是配置insecure-registries(不推荐)。具体操作:
mkdir -p /etc/docker/certs.d/harbor.internal.example.com cp harbor.crt /etc/docker/certs.d/harbor.internal.example.com/ca.crt systemctl restart docker报错二:Failed to initialize database: pq: password authentication failed
数据库密码不对。检查harbor.yml里的database.password是否和实际一致。如果之前装过又重装,可能有残留的数据卷,需要先清理:
docker compose down -v rm -rf /data/harbor/database报错三:port is already allocated
端口被占用。Harbor 默认用 80 和 443,如果这两个端口被 Nginx 或其他服务占了,需要改harbor.yml里的端口,或者先停掉占用端口的服务。
5.2 运行阶段的典型故障
故障一:镜像推送成功但 Web 界面看不到
这种情况通常是 Core 服务和 Registry 之间的通信有问题。检查 Core 的日志:
docker compose logs core | grep -i error常见原因是 Redis 连接失败或者数据库连接池满了。如果是连接池问题,调大database.max_open_conns。
故障二:漏洞扫描一直处于Pending状态
扫描任务依赖 Jobservice 和 Trivy。先检查这两个容器是否正常运行,然后看 Jobservice 的日志。如果 Trivy 的漏洞库更新失败(因为离线环境无法访问外网),需要手动更新漏洞库或者配置离线更新源。
故障三:磁盘满了导致 Harbor 无法启动
这是最棘手的情况。Harbor 的数据库和 Redis 对磁盘空间敏感,磁盘满了会直接导致服务崩溃。应急处理步骤:
- 清理 Docker 的悬空镜像和停止的容器:
docker system prune -a - 清理 Harbor 的日志文件:
/var/log/harbor/下的旧日志 - 如果还是不够,手动删除一些大的无用镜像仓库,然后执行 GC
预防措施是配置磁盘监控告警,阈值设在 80%,留出处理时间。
5.3 独家避坑技巧汇总
| 问题场景 | 排查思路 | 解决方案 |
|---|---|---|
| 登录报 401 | 检查密码、检查数据库连接 | 重置 admin 密码或检查 DB 日志 |
| 推送超时 | 检查网络带宽、检查存储后端 | 调大 chunksize、检查对象存储连通性 |
| 复制任务失败 | 检查目标仓库连通性、检查凭证 | 重新配置复制规则、检查防火墙 |
| Web 界面卡顿 | 检查数据库性能、检查 Redis | 优化 DB 索引、增加 Redis 内存 |
| 证书过期 | 检查证书有效期 | 更新证书后重启 Proxy 容器 |
还有一个容易被忽略的点:Harbor 的时区配置。默认是 UTC,如果团队在国内,日志时间会对不上。可以在harbor.yml里配置timezone: Asia/Shanghai,或者在 docker-compose 文件里给容器加TZ环境变量。
另外,Harbor 的 API 非常完善,很多操作可以通过 API 自动化。比如批量创建项目、批量添加用户、查询镜像列表等。如果你在做 CI/CD 集成,建议直接调 API,比在界面上点来点去高效得多。API 的认证方式支持 Basic Auth 和 Session,CI 场景下用 Basic Auth 更方便。
最后说一个关于升级的经验。Harbor 的跨大版本升级不能跳级,比如从 2.8 升到 2.10,需要先升到 2.9 再升到 2.10。升级前一定要备份数据库和配置文件,升级过程中 Harbor 会不可用,要安排好维护窗口。升级完成后,记得检查所有容器的状态和日志,确认没有异常报错。