Harbor私有镜像仓库搭建实战:避坑指南与运维技巧
做运维或者开发的同学多多少少都会碰到镜像管理的窘境本地机器上堆了一堆docker images来回拷 tar 包传到内网环境一多就彻底乱了又或者生产环境需要部署一套服务但容器镜像存放在公共仓库总让人不太放心万一哪天拉不下来或者被限速整个发布流程就卡住了。我自己前前后后搭过好几次镜像仓库从裸的 Registry 到带 Web UI 的 Harbor 都用过最终稳定在团队内部长期跑的还是 Harbor。这篇文章就结合实际部署过程把“搭建 Harbor 私有镜像仓库”这件事从头到尾讲透包括环境准备、安装步骤、证书配置、日常使用技巧和踩坑记录适合正在选型或准备落地私有镜像仓库的运维、开发和项目负责人参考。1. 项目概述与核心价值1.1 为什么要自建私有镜像仓库Docker 镜像本质上是分层的文件集合平时用公共镜像仓库拉取非常方便但真正进到生产或者企业内网环境问题就暴露出来了。一层是网络隔离很多机房内部根本没有连通外网就算能连几百兆甚至几个 G 的镜像在公网上传输也极不稳定另一层是安全和合规公司内部的业务镜像可能包含代码、模型、配置文件等敏感信息放在公共仓库无论如何都会有心理障碍。自建私有镜像仓库就是为了解决这些问题把镜像保存在自己的基础设施里传输走内网或者专线速度可控、权限可控、审计也可控。镜像仓库的核心角色相当于“镜像的版本管理 分发中心”。不光要能存还要能对镜像做 tag 管理、访问控制、生命周期清理。裸的registry:2容器只能满足最基本的 push/pull连个可视化的界面都没有权限控制更是靠反向代理硬搓。Harbor 正是在这个基础上做了一层完整的产品化封装目前它已经把镜像存储、Web 管理界面、用户体系和项目隔离这些能力集成得很好这也是我最终选择它的理由。1.2 Harbor 与其他镜像仓库方案的对比先聊一下候选方案这样大家在选型时心里有数。Docker 官方提供的registry镜像是最轻量的选择部署简单但功能极少适合临时用或者只用命令行操作。Portus是很多年前 SUSE 推出的一个可视化镜像仓库界面比较古老社区活跃度也不够理想。近几年国内常用的还有Nexus它是一个通用制品仓库既能存 Maven、npm也能存 Docker 镜像功能很强大但配置和资源占用都偏重单独的镜像仓库场景反而显得杀鸡用牛刀。Harbor 的优势在于专注、开源、功能全。它由项目最初由某公司开源后捐赠给云原生计算基金会CNCF孵化社区活跃度高更新迭代稳定。它原生支持多租户项目隔离、基于角色的访问控制、镜像复制、漏洞扫描、垃圾回收、审计日志等功能部署方式包含在线安装和离线安装。对国内团队来说离线安装包非常友好因为可以在有网环境预先下载好所有资源然后带到内网安装不用从公网拉取海量镜像。1.3 本次搭建的目标与适用场景我这里要做的是一套可以支撑几十人研发团队日常使用的 Harbor 私有镜像仓库部署目标是内网访问使用 HTTPS 单向认证支持多个项目分组每个项目有独立账号权限镜像能正常推送拉取并且配置了基础的磁盘清理策略。场景覆盖日常开发测试环境的镜像发布、测试服务器拉取镜像部署以及后续需要对接持续集成流水线CI/CD。这套方案的核心技术栈是Docker Docker Compose Harbor。Harbor 官方安装包内部封装了多个组件包括Harbor Core核心 API、Registry镜像存储、Nginx反向代理、PostgreSQL数据库、Redis缓存等。其实不需要手动一个个部署使用官方提供的 installer 脚本就能一键完成但前提是 Docker Compose 环境要准备好。2. 环境准备与部署方案设计2.1 基础环境要求Harbor 对服务器配置要求并不高最主要的瓶颈是磁盘 IO 和容量。镜像仓库本质上是存储服务读多写多建议至少 4 核 CPU、8GB 内存如果是几十人团队的日常使用这个配置绰绰有余。磁盘方面操作系统盘和数据盘建议分开数据盘走独立挂载容量根据镜像增速预留。这里有一点很重要Harbor 的镜像实际存储目录默认是在/data下如果系统盘不够大必须提前挂载大容量数据盘否则运行几个月就等着磁盘告警吧。操作系统我建议用 Ubuntu 22.04 LTS 或 CentOS 7.9如果你的环境用的还是 EulerOS、Kylin 这些国产发行版只要能正常安装 Docker 和 Compose 就可以Harbor 本身跑在容器里对宿主机系统不是特别挑剔。需要注意内核版本不能太低否则 Docker 的存储驱动和网络模式会出各种奇怪问题。2.2 安装方式选型Harbor 的部署方式主要分两类在线安装和离线安装。在线安装需要服务器能访问外网执行 installer 时会从 Docker Hub 拉取相关镜像包包括goharbor/harbor-core、goharbor/registry、goharbor/nginx-photon等等。这种方法省去下载安装包的步骤但依赖网络且下载速度不稳定。离线安装则更稳妥。去官方 Release 页面下载名为harbor-offline-installer-v2.x.x.tgz的压缩包里面既包含安装脚本也包含所有 Docker 镜像的 tar 包。安装时脚本会把这些 tar 包导入到本地 Docker 环境整个过程完全不需要外网。我强烈推荐离线安装不只是因为内网环境用得上就算在有网环境离线包也能避免重复拉取带来的时间浪费而且版本锁定可复现性更好。2.3 域名与证书规划Harbor 默认支持通过 IP 地址访问但在生产环境使用 IP 访问会有很多不便比如 Docker 客户端登录时如果 registry 地址是 IP镜像 tag 名称就会变成192.168.x.x:443/project/image。如果使用域名比如harbor.example.local看起来更清晰且后续如果迁移服务器只用改 DNS 解析镜像 tag 无需变动。因此建议提前规划一个内网域名。证书方面我建议使用自签 CA 证书因为内网环境不太可能申请到公网证书自签证书需要注意把所有客户端机器的 CA 证书都信任一遍。还有一种方式是在安装 Harbor 时直接配置 HTTP但是 Docker 对 HTTP 仓库默认是拒绝的需要在每个客户端配置 insecure-registries非常繁琐且不安全。所以无论多麻烦我还是推荐走 HTTPS。3. 实操从零搭建 Harbor3.1 安装 Docker 与 Docker Compose这一步是基础。先更新系统然后添加 Docker 官方软件源安装docker-ce、docker-ce-cli、containerd.io和docker-compose-plugin。以 Ubuntu 为例安装完成之后不要忘了启用 Docker 服务systemctl enable --now docker docker version docker compose version为什么要用docker compose而不是老旧的docker-compose新版 Compose 作为 Docker 的插件集成版本更新更及时命令格式也更统一。Harbor 的安装脚本本身会调用docker-compose命令所以需要确认该命令是否存在版本不要太低。我个人通常做一个软链接兼容ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose这个细节很关键如果不做兼容处理Harbor 安装脚本可能会报“command not found”。另外宿主机的时间同步也要检查镜像仓库涉及日志审计和复制调度时间漂移会导致很多难以排查的问题。3.2 下载并配置 Harbor到 Harbor 的官方 GitHub Release 页面下载离线安装包这一步建议在有网的开发机上完成然后再传到目标服务器。比如我下载的是harbor-offline-installer-v2.10.0.tgz解压后目录结构如下tar -zxvf harbor-offline-installer-v2.10.0.tgz cd harbor目录里最重要的文件是harbor.yml.tmpl这是配置模板。我们需要把它复制一份成harbor.yml然后修改关键参数。在一次真实部署中我把核心配置简化成下面这个样hostname: harbor.example.local http: port: 80 https: port: 443 certificate: /data/cert/harbor.example.local.crt private_key: /data/cert/harbor.example.local.key harbor_admin_password: YourStrongAdminPassword123 database: password: YourDBPassword456 data_volume: /data/harbor log: level: info local: rotate_count: 10 rotate_size: 100M需要注意的坑有哪些hostname一旦确定尽量不要再改因为后续 Docker 客户端的镜像 tag 会绑定这个字段。harbor_admin_password是初始化时管理员的密码长度和复杂度一定要满足要求否则登录会出问题。database.password是 Harbor 内部数据库的密码这个也是只在初始化时生效。data_volume建议专门挂载大容量磁盘和系统盘分开。3.3 生成 HTTPS 证书并启用这里直接生成自签 CA然后签发 Harbor 服务器证书。大概分三步创建 CA 私钥和根证书创建 Harbor 服务器私钥并生成签名请求最后用 CA 签名并生成最终证书。为方便演示在这里用明文命令说明关键步骤。第一步生成 CA 私钥和根证书。mkdir -p /data/cert cd /data/cert openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -subj /CNHarbor-CA -out ca.crt第二步生成服务器私钥和证书签名请求。openssl genrsa -out harbor.key 2048 openssl req -new -key harbor.key -out harbor.csr -subj /CNharbor.example.local第三步新建一个扩展文件写上 SANSubject Alternative NameIP 地址和域名都要加上否则 Docker 校验证书时会发现证书不匹配。cat ext.cnf EOF subjectAltNameDNS:harbor.example.local,IP:192.168.1.100 EOF openssl x509 -req -in harbor.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out harbor.crt -days 3650 -sha256 -extfile ext.cnf在执行官方安装脚本之前需要把harbor.yml里的https.certificate和https.private_key路径指向刚才生成的harbor.crt和harbor.key。这一步如果不做安装时如果路径无效脚本会直接报错退出。3.4 部署 Harbor 并验证接下来执行安装脚本sudo ./install.sh这个脚本会导入镜像包、生成 docker-compose 配置并启动所有服务。正常情况下等待几分钟后使用docker compose ps可以看到容器状态全部是 healthy。我通常再确认一下监听端口ss -tlnp | grep -E 80|443看到 80 和 443 都在监听说明 Nginx 反代已经起来了。浏览器访问https://harbor.example.local如果之前没有信任 CA 证书浏览器会提示不安全这个属于正常现象选择高级继续访问即可但要注意后续每台客户端都需要把证书放到系统信任链里Docker 才会信任。首次登录使用admin 初始化密码进入系统后第一件事是修改管理员密码然后开始配置项目。这里建议管理员账号不要给所有开发人员使用而是创建独立账号按需分配项目权限这样审计日志才有意义。4. 核心功能配置与使用技巧4.1 Harbor Web 界面与项目管理登录 Harbor 后左侧菜单能看到“项目、镜像仓库、日志、垃圾回收、配置管理”等核心模块。项目就是一个命名空间Docker 镜像的 tag 前缀就是项目名例如harbor.example.local/demo/my-app:v1.0其中demo就是项目名。创建项目时可以勾选访问级别为“公开”或“私有”公开项目允许所有用户匿名拉取如果仓库整体是私有网络的话私有项目需要授权。我强烈建议默认创建私有项目然后针对项目添加成员并分配角色。角色分为仓库管理员、开发者、访客等。开发者可以推送和拉取镜像访客只能拉取镜像。这样开发人员只拥有自己所在项目的写权限不会干扰其他项目。给团队成员授权的时候还有个细节Harbor 支持有项目管理员创建账号并绑定角色不同项目可以互相隔离。实际使用中我们通常一个业务线建一个项目成员单独拉进各自的组这样权限清晰镜像也容易找。4.2 配置 Docker 客户端登录与推送客户端要登录 Harbor必须先把 Harbor 的 CA 证书加到系统信任链。以 Ubuntu 客户端为例sudo cp /data/cert/ca.crt /usr/local/share/ca-certificates/harbor-ca.crt sudo update-ca-certificates然后 Docker 登录docker login harbor.example.local输入账号密码提示Login Succeeded就代表连接成功。接下来给本地镜像打标签并推送docker tag nginx:latest harbor.example.local/demo/nginx:v1.0 docker push harbor.example.local/demo/nginx:v1.0这里有两个常见问题。第一个是如果不信任 CA登录时会报certificate signed by unknown authority解决方法就是刚才那两步或者把证书放到/etc/docker/certs.d/harbor.example.local/下Docker 会优先使用该目录下的证书。第二个是如果是 HTTP 方式访问Docker 会直接拒绝必须修改/etc/docker/daemon.json里的insecure-registries但这种方式不建议自签 HTTPS 才更安全。另外推送时如果没有给镜像打上 Harbor 的地址前缀和项目名称会报错denied: requested access to the resource is denied。需要先打标签再推送这个新手最容易踩。4.3 镜像复制与垃圾回收镜像复制功能我觉得是 Harbor 的一大杀手锏。它的使用场景是开发环境在 A 地区生产环境在 B 地区两个环境之间网络隔离但需要把验证通过的镜像同步到生产镜像仓库。Harbor 内置了复制管理只需要配置一个复制规则源仓库和目标仓库都关联好一旦源镜像 tag 更新就会自动或手动同步过去。我们实际用它实现了“开发仓库 → UAT 仓库 → 生产仓库”的多级同步链路非常省力。配置复制规则时需要注意目标仓库的地址、账号要有写权限复制模式可以选择 Push-based由源仓库主动推送到目标或 Pull-based目标仓库主动拉取源镜像。网络不通的情况下可以选择定期拉取模式甚至让目标仓库在空闲时段去拉取避免高峰带宽占用。复制完成后一定要回去看任务状态有一个“呈现最近作业”的列表每次成功失败清清楚楚。垃圾回收是另一个必须养成的习惯。镜像仓库在删除 tag 或者镜像后底层的层数据并不会立即删除实际上磁盘空间还是一直被占用。Harbor 的垃圾回收功能可以清理这些无用的层数据但需要注意垃圾回收期间建议停止推送操作否则可能造成部分镜像的层数据引用不一致。实操时我们通常安排在凌晨触发并在 Web 界面上勾选“不进行清单”减少风险。4.4 用户权限与安全策略安全策略的落地我从三个层面说。第一是账户管理Harbor 默认使用本地数据库用户体系但同时也支持接入 LDAP 和 OIDC。我们有部分团队接入了 LDAP好处是人员入职离职自动同步权限不用手工创建账号。第二是认证策略Harbor 的 Web 界面支持强制让用户定期修改密码登录失败次数多了还会锁定账户这些在“配置管理”里可以调整。第三是操作审计每个推送、删除、复制操作都会记录在“日志”模块中出现问题可以直接按时间检索定位到具体操作人。还有一个平时很容易忽略的安全点Harbor 自带的漏洞扫描功能支持对镜像层进行 CVE 扫描扫描器默认从公共 CVE 库拉取数据在内网环境可能需要提前配置漏洞数据库离线包。虽然不能完全替代专业的镜像安全扫描工具但有总比没有强至少能排查出基础系统镜像的已知漏洞我们把它用在 CI 流水线的前置检查有一定效果。5. 常见问题与排查实录5.1 登录报错与 HTTP/HTTPS 配置问题最常见的错误就是 Docker 登录时报Error response from daemon: Get https://harbor.example.local/v2/: x509: certificate signed by unknown authority。这个问题的根源是客户端没有信任 Harbor 的 CA。解决办法按照前面说的把ca.crt复制到系统信任链或者放到/etc/docker/certs.d/harbor.example.local/目录下重启 Docker 再登录即可。如果你偏要用 HTTP那就在/etc/docker/daemon.json中配置insecure-registries但我不推荐。另外一个隐蔽问题如果 Harbor 的hostname配置的是域名但客户端无法解析该域名登录也会超时或者报错。需要在每台客户端的/etc/hosts加入一条记录或配合内网 DNS 打通否则就算证书没问题也连不上。5.2 磁盘空间不足与 GC 策略镜像仓库跑久了磁盘占用增长非常快。很多人发现docker images删了一大堆但 Harbor 服务器上的磁盘依然爆满原因就是没有执行垃圾回收。GC 的执行分两个步骤先清除软删除的镜像标记再清理存储目录。在使用 GC 时必须掌握一个原则不要在 GC 进行时推送镜像否则可能被标记为“已软删除”的层被复用出现镜像损坏。我的做法是配置一个定时任务脚本在凌晨 2 点调用 Harbor API 触发 GC并搭配 log rotate 控制日志大小。另外对于数据盘要设置监控告警这里我建议使用磁盘容量达到 70% 时告警达到 85% 时必须启动紧急 GC 和镜像滚动清理否则撑不了几个工作日。脚本里面调用 API 时可以用管理员账号生成一个机器人账号专门用于 GC 触发和状态查询而不是把管理员密码放在脚本里这个习惯可以降低账号泄露风险。5.3 高并发与性能调优团队规模扩大后镜像仓库的并发拉取请求会明显增加。Harbor 的前置 Nginx 默认配置吞吐能力足够瓶颈往往在于存储层和 Registry 的并发能力。早期我们用机械盘存储多个任务同时推送镜像时经常出现超时和 io 延迟飙升后来换了 SSD 后明显改善。如果数据量过大可以考虑把/data/harbor放到独立的快存储上先跑一段时间观察 IO 指标再决定是否迁移。这里要提醒一点如果以后镜像量特别大建议搭配对象存储比如兼容 S3 的存储作为后端但配置复杂度会上升。性能调优的另一个层面是镜像分发加速。Harbor 本身支持在多个节点部署同一套实例通过负载均衡对外提供服务但数据库和缓存需要共享。如果不想搞那么复杂可以通过 Harbor 的镜像复制功能把常用镜像复制到每个机房的本地仓库拉取请求直接命中本地跨机房带宽占用问题也就少了。5.4 升级与备份恢复Harbor 版本升级其实不难但必须按官方流程走。首先要备份数据库和存储目录然后下载新版本离线包运行./install.sh --upgrade脚本。在这里我吃过一次亏直接从次新版本跳到更的版本跨度很大数据库迁移脚本会执行很多步骤一旦中间报错整个服务就起不来了。所以一定要先在测试环境完整跑一遍升级再操作生产环境同时升级前快照或者完整备份。备份恢复的实操经验是数据卷/data/harbor和数据库要分开理解。Harbor 的元数据用户、项目、复制规则等存在 PostgreSQL 中而镜像的二进制层数据存在数据卷里。如果只是备份了数据卷而没有备份数据库恢复后镜像数据可能和元数据对不上反过来如果只备份数据库而没有备份数据卷恢复后镜像会全部丢失。完整的备份策略是数据库用pg_dump导出数据卷用 rsync 或者 tar 打包再配合对象存储定期上传。恢复的时候有一个小技巧先安装一个全新的 Harbor 实例版本尽量保持一致然后用备份的数据库覆盖新实例的数据库再同步数据卷最后启动服务。整个过程不能跨大版本否则数据库 schema 不兼容。某些场景下如果只是迁移服务器建议直接在新服务器上用同样安装包重新安装再把旧数据卷和数据库整体搬过去这样的成功率反而更高。6. 扩展思考与 CI/CD 流程的集成搭建好 Harbor 之后第一个真正发挥威力的场景就是持续集成持续发布。我们的团队并没有把镜像仓库独立使用而是把它作为流水线中的一环。具体流程是代码提交触发构建任务把生成的镜像打好 tag 推送到 Harbor 的开发项目测试环境直接从 Harbor 拉取对应 tag 的镜像部署验证通过后通过复制规则同步到生产仓库同时更新 Jenkins 或 GitLab CI 中的部署配置。在使用 API 时可以给流水线建立一个机器人账号Harbor 中“机器人账户”是专门为自动化场景设计的可以指定权限范围比如只允许推送某个项目。它的好处是没有普通用户的密码生命周期限制即使不可用也可以在 UI 中一键吊销比把管理员密码硬编码到流水线安全得多。写到这里发现其实还有很多细节可以继续展开比如如何配置镜像自动清理策略来避免仓库无限膨胀、如何用 Webhook 在镜像推送完成后自动通知部署系统、如何基于 Harbor 的 OIDC 对接公司内部统一的身份认证。不过这些都是在完成基础搭建之后因地制宜的东西先把基础环境跑稳再说。最后说一点个人经验Harbor 这个项目有一个特性就是你没有踩过坑之前会觉得它太简单了真正用起来之后才发现它的复制、GC、安全和升级机制都是在一个一个真实场景中磨出来的。搭建本身半天就能完成但要想稳定服务团队一年甚至更久一定要做好磁盘监控、备份策略和权限规划。这几点在平时不会刷存在感可一旦出问题就会让你觉得当初多花的时间非常值得。