先交代一下背景。Harbor是我这几年的工作里部署次数最多的开源项目之一,从最早在Ubuntu 18.04上折腾,到后来20.04、22.04都反复装过。它本质上是一个开源的容器镜像仓库,用来集中管理Docker镜像,带Web界面、项目隔离、镜像签名、漏洞扫描这些能力。如果你所在团队还在用公共仓库管理私有代码的构建产物,或者一台台服务器手动拷贝镜像,这篇文章就是给你准备的。我会把在Ubuntu 18、20、22三个版本上完整安装Harbor的流程、配置说明和踩坑记录全部整理出来,每一步都给出具体命令和参数,照着做基本能一次成功,装完之后也知道怎么传镜像、怎么排查问题。
1. 为什么选Harbor?动手安装前先想清楚几件事
1.1 自建镜像仓库到底解决了什么问题
很多团队一开始用Docker,镜像都是本地build完就丢,或者塞到同一个公共仓库的私有空间里。等到机器一多、环境一复杂,问题就来了:开发环境要的镜像版本和生产环境对不上、内网服务器拉不了外网镜像、仓库没有权限控制,谁都能动。
Harbor这类私有镜像仓库解决的核心问题有三个。第一是本地化存储,镜像全部存在内网服务器上,拉取速度快,不依赖外网。第二是权限项目隔离,可以按团队建项目、按用户分配读写权限,生产环境该谁推镜像、该谁拉镜像都说得清。第三是生命周期管理,镜像删除、清理、漏洞扫描、复制同步都有现成功能,不需要自己拿脚本拼。
自建方案里,Harbor的普及度是最高的。接口规范、文档全、社区活跃,UI做得也不像某些开源项目那么"程序员审美",给团队内部使用基本零学习成本。这也是我这几年来回折腾之后稳定用它而不是其他替代品的原因。
1.2 Ubuntu版本选型前需要知道的差异
Ubuntu 18.04、20.04、22.04虽然都叫Ubuntu,但对于部署Harbor来说差异比想象中大,主要集中在三块:Docker安装方式、Docker Compose的命令形态、以及系统底层组件(iptables、cgroup)的行为差异。
| Ubuntu版本 | Docker Compose方案 | 主要坑点 |
|---|---|---|
| 18.04 | 官方GitHub下载二进制1.29.2 | apt源里Compose版本太老,系统已EOL |
| 20.04 | apt安装docker-compose-plugin或下载二进制 | 相对稳定,踩坑最少 |
| 22.04 | apt安装docker-compose-plugin(V2命令形态) | nftables与旧版Docker不兼容、cgroup v2 |
简单说,20.04是最省心的,18.04和22.04都有需要注意的地方。这篇教程后面的内容会把这些坑逐个拆开讲,不会让你装到一半卡住才发现问题。
2. 环境准备:装Harbor之前必须先搞定的四件事
2.1 Docker引擎安装:官方源是唯一推荐
Harbor依赖Docker运行,这是一个套在鸡蛋外面的筐,必须先装好。我试过Ubuntu自带的apt源直接搜docker.io装,版本老得离谱,Harbor的install.sh脚本对Docker版本有要求,装完大概率报deprecated或直接跑不起来。所以老老实实用Docker官方源。
# 以Ubuntu 22.04为例,18.04把jammy换成bionic,20.04换成focal sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io装完验证一下:
sudo docker run hello-world能正常打出提示就算过了。
2.2 Docker Compose:18.04和22.04完全是两种玩法
Harbor是用docker compose把一堆容器编排起来的,所以Compose必须装好,而且版本不能太老。这是整个部署过程里最容易忽略的一步。
Ubuntu 20.04和22.04可以直接用Docker官方源装V2插件:
sudo apt install -y docker-compose-plugin装完之后命令是docker compose(注意中间有个空格),V2的兼容性非常稳,后面所有操作都用这个。
Ubuntu 18.04就别指望apt了。18.04默认的docker-compose是1.17,Harbor要求至少1.18以上,安装脚本会直接崩溃。我的做法是从GitHub上下载1.29.2的二进制文件,这是V1的最终版本,是老系统上兼容性最好的一版:
sudo curl -L "https://github.com/docker/compose/releases/download/v1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose装好之后执行docker-compose --version确认。注意18.04环境上如果还装了什么python2的残余组件,有时候会干扰Compose运行,实测下来关掉系统的python2相关服务一般能解决。
2.3 硬件内存与磁盘规划:说多了都是泪
Harbor的组件很重,不是一个小软件。完整安装(含漏洞扫描组件Trivy)之后,空载内存占用大概在2GB到2.5GB之间。我见过有人在1GB内存的云主机上装,装完界面都打不开,Harbor核心服务反复重启。
内存和磁盘规划建议直接看下表:
| 配置项 | 最低要求 | 建议值 |
|---|---|---|
| 内存 | 2GB | 4GB及以上 |
| CPU | 2核 | 4核及以上 |
| 系统盘 | 20GB | 50GB |
| 镜像数据盘 | 50GB | 按镜像增长速度预留 |
磁盘这里多说一句:Harbor的数据目录默认在/data,里面存的都是数据库和镜像层文件,一旦塞满会导致push镜像是报错no space left on device。如果机器上有独立的数据盘,强烈建议把数据目录挂到独立分区上,比如把2TB的数据盘挂载到/data。这比事后迁移数据轻松得多。
3. 下载Harbor安装包:离线包为什么是我唯一推荐
3.1 在线包与离线包的对比
Harbor官网给两种安装包:在线安装包(online installer)和离线安装包(offline installer)。我直接给结论:生产环境、甚至测试环境都别用在线包,用离线包。
原因很简单。在线安装包本身只有几十MB,安装过程中会去Docker Hub拉取Harbor的所有组件镜像。国内网络环境大家心里都有数,一个镜像二三十个,每个几百MB,拉一半断了就要从头再来。离线包里所有镜像全部打包成tar文件,一次下完,本地导入,安装过程几乎不依赖外网。
我推荐用离线安装包。
Harbor的GitHub Releases页面会提供这两类安装包。离线包文件名类似harbor-offline-installer-v2.8.4.tgz,体积大概在600MB到900MB之间,具体取决于版本和附带组件的多少。下载后先做一件事:校验sha256,避免文件损坏导致解压时报错。
sha256sum harbor-offline-installer-v2.8.4.tgz和官方页面上提供的校验值比对,一致再解压。
3.2 版本选择:别追新,用稳定分支
Harbor大版本从1.x迭代到了2.x,目前新特性(比如OCI支持、更好的复制策略)都在2.x上。装国内团队用的版本,我建议直接选2.5以上的最新2.x稳定版,不要用2.0、2.1这些早期版本,有些API和UI都不成熟。
版本号旁边会有v2.8.x、v2.9.x这种,挑Release标志最新、且没有rc、beta字样的就行。一个经验:装之前看一眼它的harbor.yml.tmpl文件里的_version字段,不同版本配置项略有差异,但下面讲的核心配置在所有2.x版本上都通用。
解压命令:
tar -xzf harbor-offline-installer-v2.8.4.tgz cd harbor ls -l你会看到harbor.yml.tmpl、install.sh、common.sh这些文件。下一步就是复制配置文件开始改配置。
4. 手把手配置harbor.yml:每个参数背后的逻辑都要讲清楚
4.1 最核心的基础配置项
进入harbor目录之后,先把模板复制成正式配置:
cp harbor.yml.tmpl harbor.yml打开文件,重点配置以下内容。
hostname: 192.168.1.100 http: port: 80 harbor_admin_password: Harbor12345 database: password: root123 data_volume: /data/harborhostname这个参数是整个配置里最关键的一个。它决定了Harbor在页面上显示的访问地址,也是后续docker login时要用的地址。很多新手把它留成reg.mydomain.com这种域名,结果本地没有DNS解析,登录全部失败。我的建议是:内网测试直接填服务器IP,生产环境填你规划好的内部域名,并保证所有要拉镜像的机器能解析到这个域名。
http.port默认80,如果这台机器上已经跑着Nginx或者其他Web服务,80端口肯定被占用。这时候改成8080或者别的空闲端口,后面访问地址就要带端口号,比如http://192.168.1.100:8080。改端口是最省事的绕开冲突方案,不要再费劲去折腾反向代理,那是后话。
harbor_admin_password是系统初始化管理员admin的密码。默认值是Harbor12345,这是公开的官方默认值,一定要改成一个足够复杂的密码,否则装完就等于把仓库大门敞开。数据库密码同理,Harbor内部PostgreSQL连接用的密码,默认值也要改。
4.2 HTTPS、组件选择和数据目录
配置文件里https段默认是注释掉的,里面有证书路径、私钥路径两个参数。如果内网环境没有正规CA签发的证书,我的建议是:测试环境直接注释掉HTTPS,用HTTP跑通流程,后面再考虑证书。否则自签证书折腾完,客户端那边信任链又是一大堆问题。
看一下常见的配置取舍:
| 配置项 | 测试环境建议 | 生产环境建议 |
|---|---|---|
| https | 注释掉,用HTTP | 正规证书,开启HTTPS |
| data_volume | 默认/data | 独立数据盘目录 |
| trivy | --with-trivy打开扫描 | 打开扫描 |
| chartmuseum | 不用就关闭 | 需要管理Helm Chart才开 |
数据目录建议改成/data/harbor这种带子目录的路径,和系统其他数据区分开。以后备份、迁移、看磁盘占用都一目了然。
组件选择上,install.sh脚本支持几个可选参数:
./install.sh --with-trivy--with-trivy是用来启动漏洞扫描组件的。我建议加上,镜像安全扫描现在基本是标配了。但需要注意,Trivy首次启动时要下载漏洞数据库,如果服务器访问外网慢,这个组件会一直处于starting状态,这时候不要慌,等它下载完,或者手动pull一下相关组件镜像即可。
4.3 修改配置之后的热加载逻辑
这里有一个很多人不知道的点。改完harbor.yml之后,不需要重新下载任何包,重新跑一遍install.sh就行。脚本会自己检测已有环境,重新生成配置并更新容器。之前push进去的镜像不会丢,数据卷是持久化存在的。
但要注意一点:不要在Harbor运行期间手动去改docker-compose.yml或者删掉某个容器,所有配置变更都通过改harbor.yml再跑install.sh来完成。这是官方支持的做法,绕开它自己去搞容易把部署搞坏。
5. 执行install.sh装Harbor,以及第一次上传镜像的全过程
5.1 安装执行与运行状态验证
配置改好之后就可以正式安装了:
sudo ./install.sh --with-trivy安装脚本执行过程大概有这么几步:导入离线镜像、生成docker-compose编排文件、启动所有容器。期间会有大量docker load的日志输出,等就是了。如果没装Trivy,直接sudo ./install.sh。
装完看到类似Harbor has been installed and started successfully.的提示就算成功了。用下面的命令验证容器状态:
docker compose ps正常情况下你会看到以下这些容器处于Up状态:harbor-core、harbor-db、harbor-jobservice、harbor-portal、harbor-registry、nginx、redis、registryctl,如果加了Trivy,还会有harbor-trivy。
nginx容器是整个Harbor流量的入口,外面访问的80(或指定端口)就是它暴露出来的。如果nginx没起或者重启,浏览器大概率会直接连不上。
浏览器打开http://192.168.1.100,用admin和你改过的密码登录,就能看到Harbor控制台界面。到这里安装就算完成了,但是离真正可用还差最后一步——把镜像推进去。
5.2 创建项目、命令行登录与push镜像
Harbor里组织镜像的单元是项目(Project),类似于公共仓库里的namespace。在界面左上角点"新建项目",填一个项目名,比如library,可见性选私有(Private),创建即可。
然后到一台装了Docker的客户端机器上执行以下操作:
# 1. 给镜像打上Harbor仓库地址的tag docker tag nginx:latest 192.168.1.100/library/nginx:latest # 2. 登录Harbor仓库 docker login 192.168.1.100 -u admin -p YourPassWord # 3. push镜像 docker push 192.168.1.100/library/nginx:latest如果在客户端机器上直接执行,会遇到一个高频报错:
Error response from daemon: Get "http://192.168.1.100/v2/": http: server gave HTTP response to HTTPS client这个错误的原因很明确:Docker客户端默认会用HTTPS去访问Registry,而你的Harbor暴露的是HTTP。解决办法是在客户端机器的/etc/docker/daemon.json里声明这是非安全仓库:
{ "insecure-registries": ["192.168.1.100"] }然后:
sudo systemctl restart docker再重新登录、push。注意insecure-registries里如果端口不是80,要写成192.168.1.100:8080这种带端口的形式。
6. Ubuntu 18/20/22各自最容易翻车的安装坑
6.1 Ubuntu 22.04:nftables导致容器端口外部访问不通
22.04系统上最常见的一个现象:Harbor装完,在服务器本机curl没问题,页面也打得开,但换一台机器访问服务器IP的80端口,死活不通。
排查下来十有八九是iptables-nft的问题。Ubuntu 22.04默认的iptables后端是nftables,旧版本Docker对nftables的兼容性有缺陷,导致发布端口规则没有正确写入。
解决办法非常简单:把Docker升级到20.10.14以上版本,新版本已经能正确处理nftables。装Docker的时候直接用2.1里的官方源流程装最新版,就不会撞上这个坑。如果你用的是旧版Docker、一时无法升级,也可以把iptables切回legacy模式的:
update-alternatives --set iptables /usr/sbin/iptables-legacy但这个方法治标不治本,尽量优先升级Docker版本。
另外22.04的cgroup v2和Docker配合,需要Docker 20.10以上才完全没问题,这又是一个升级Docker的理由。别图省事装老版本,成本都在后面。
6.2 Ubuntu 18.04:EOL系统上的Compose和源问题
18.04的问题集中在一个词:老。系统本身已经停止维护了,apt源默认指向archive源,速度慢且有些包装不上。如果你不得不在这上面部署,先更新源再装东西。
真正卡住很多人的是Docker Compose版本。18.04的apt源里docker-compose只有1.17,Harbor的install.sh要求1.18以上。解决办法在2.2已经写过了:下载1.29.2二进制覆盖安装。这里再补一句,装完二进制后先把系统里apt版docker-compose卸掉或者rename掉,否则在非root用户下可能还是调用到旧版。
还有一个隐藏坑:18.04上的glibc版本相对较老,Harbor的最新版本(比如2.9)有时候跑一些组件时会报段错误或非法指令。如果遇到这类问题,不要死磕最新版,退到2.5.x或2.6.x稳定版本,立刻就能起来。老系统配老版本是这个场景里的妥协之道。
6.3 所有版本通用:80端口到底被谁占了
Harbor默认端口80和443在服务器上非常容易冲突。我遇到过最常见的占用者是Nginx、Apache和一堆开发环境里的Node应用。
部署Harbor之前先做一次端口探测:
sudo ss -tlnp | grep -E ':(80|443)\s'如果有进程监听,要么把它挪走,要么改Harbor端口。我的建议是改Harbor的http.port而不是去动已有的服务。Harbor的自定义端口支持得很好,改动成本比迁移一个Nginx站点低得多。
7. 安装Harbor常见故障排查:这些问题我基本都遇到过
7.1 登录、push、pull环节的报错速查
下面这组问题几乎每个新装Harbor的团队都会遇到,我直接做成速查表:
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
| server gave HTTP response to HTTPS client | 客户端未信任HTTP仓库 | daemon.json配置insecure-registries |
| x509: certificate signed by unknown authority | 自签证书不被信任 | 配置客户端CA,或先退回HTTP |
| connection refused | 端口没监听或被防火墙拦截 | 检查Harbor容器状态、ufw放行端口 |
| unauthorized: authentication required | 没登录或账号无权 | docker login先登录,检查项目权限 |
| 413 Request Entity Too Large | Nginx传输限制 | 检查Harbor nginx配置或客户端代理 |
| no space left on device | 磁盘满 | 清理数据盘,扩容 |
防火墙这里多说一句。Ubuntu默认开的是ufw,新版本下ufw如果没有放行端口,外部访问直接被丢弃:
sudo ufw allow 80/tcp sudo ufw allow 8080/tcp在服务器本机curl正常、外部机器不通的情况下,优先怀疑防火墙,而不是Harbor配置。
7.2 密码改完了却登录不上的情况
Harbor默认管理员密码改了之后,如果忘记,可以通过直接操作数据库重置。我分享一个能用的流程:
# 进入harbor-db容器 docker exec -it harbor-db psql -U postgres -d postgres # 执行SQL修改admin密码(先构造一个HTTPS密码的BCrypt哈希) UPDATE harbor_user SET password = '$2a$10$...', salt = '' WHERE username = 'admin';实际重置时比较麻烦的是生成BCrypt哈希,更省事的方案是趁着还没忘,把当前密码调整到一个好记且稳的强密码,然后用环境变量文件harbor.yml里的harbor_admin_password重新./install.sh跑一遍,这个方法也能重置admin密码,并且不会丢数据。
7.3 磁盘空间、权限和数据目录的问题
Harbor容器是以指定用户运行的,如果数据目录的属主不对,会出现容器刚启动就退出的情况。一个简单通用的修复手段:
chown -R 10000:10000 /data/harbor这里的10000:10000是Harbor内部使用的UID/GID。改成这个属主后重启容器,绝大多数权限类问题都能解决。
磁盘空间问题除了扩容,日常运维也可以定期做镜像GC(垃圾回收)。Harbor界面里有"GC"功能,它会清理掉那些被标记删除但还没释放的镜像层。注意GC期间不要做push和pull操作,会锁registry,安排一个低峰期执行。
8. 安装完成之后的几句实话
Harbor装完不代表事情结束,真正的坑往往在使用过程中才冒出来。我个人的体会是,先用起来最重要:让团队开始把镜像往Harbor上推,把现有流程的拉取地址切换过来,用真实业务去逼出问题。
几个后续要立刻做的事,按优先级排:改完默认密码之后把访问令牌(机器人账号)用起来,别让所有人的构建脚本都抱着admin账号跑;定期备份Harbor数据库,因为镜像仓库本身就是资产,数据库丢了项目结构全乱;对项目做租户隔离,不同团队别混在一个项目里,权限清晰一点后面省很多沟通成本。
如果你后续有更进阶的需求,还可以研究Harbor的远端复制功能,把测试环境和生产环境的镜像做同步,或者接上钉钉、企微的Webhook,让镜像推送通知直达群里。这些功能都是现成的,安装阶段不用管,先保证能顺畅地推拉镜像比什么都强。
Ubuntu 18、20、22三个版本跑下来,最省心的其实是20.04,但不管哪个版本,核心思路都一样:官方源装Docker、选离线包、改对harbor.yml、跑install.sh、配好insecure-registries。按这个节奏走,基本不会被卡在半路。