简介:这是一份Harbor v2.5.0-rc1的离线安装资源,面向需要在内网或隔离环境部署容器镜像仓库的运维与开发人员,解决因无法访问公共镜像源而导致的安装、部署困难。资源共6个文件,以shell安装脚本、YAML配置模板、license许可文件及离线镜像压缩包等类型为主,整体约623.92MB,内置了Harbor服务镜像、安装入口脚本、公共处理脚本及配置准备工具,用户只需按模板修改配置并执行脚本即可完成安装。该资源包已有254人学习下载,适合具备一定容器基础、希望高效部署Harbor的工程技术人员。通过该离线包,使用者可以快速搭建私有镜像仓库,同时借助脚本和配置文件理解Harbor各组件的关系与参数含义,为后续生产环境的定制与运维提供可靠参考。 Harbor 是我这几年用下来最顺手的私有镜像仓库,没有之一。每次接手新环境,第一件事就是把harbor-offline-installer-v2.5.0-rc1.tgz这个包推过去,解压、改配置、跑install.sh,基本就是这三板斧。虽然它名字里带 rc1,但 v2.5.0 的候选版本在功能层面已经冻结,拿来做预发环境甚至小规模生产,完全够用。这篇博文我就从头到尾写一遍:离线安装包的结构、Ubuntu 环境怎么准备、部署时的关键参数,以及很多人躲不开的 http 改 https 的实操。照着做,基本不会踩坑。
1. 这个离线安装包里到底有什么
很多人拿到 tgz 就开始解压,实际上我建议先花十秒钟看看包的结构,能省掉后面不少疑惑。用tar -tzf harbor-offline-installer-v2.5.0-rc1.tgz查看包内文件列表,你会看到一个相对清爽的结构:install.sh、prepare、harbor.yml.tmpl、common.sh、harbor.v2.5.0.tar.gz,另外还有 license 和 readme 之类的说明文件。
看到这里,包的类型基本就明确了。Harbor 官方提供两种安装器:online-installer 和 offline-installer。名字已经说明问题——online 的包很小,脚本在安装时会去外部拉取所需 Docker 镜像,服务器必须能连通外部镜像源;而 offline 包把 goharbor 相关的所有镜像提前打进了harbor.v2.5.0.tar.gz,安装时直接用docker load载入。
这里的 offline 不是说机器完全不能联网,而是指不依赖外部网络资源。这带来的直接好处是:内网服务器没有外网访问权限时,照样能完整部署一套 Harbor。我帮朋友公司搭环境时,很多服务器都在隔离得很干净的网段里,outbound 访问基本不存在,online 安装器直接没法用,这种离线包才是唯一正确打开方式。
1.1 离线包设计的隐藏优势
离线包还有一个很多人忽略的隐藏优势:版本一致性。harbor.v2.5.0.tar.gz里面锁定了所有组件的镜像 tag,core、portal、registry、jobservice、trivy 这些镜像都是 v2.5.0-rc1 这一套,不会因为你安装当天在线源更新了某个 tag 导致版本漂移。
排障成本也随之降低。所有东西都在本地,加载镜像失败就看磁盘和权限,容器起不来就看配置和依赖,干扰项比在线安装少得多。对于生产环境来说,可重复、可预期远比"装个最新版"重要,这也是我这些年越来越倾向离线包的原因。
2. 部署前的环境准备
任何安装类问题的根子,九成在环境没准备好。Harbor 看起来就是一坨 docker compose,但它对底层 Docker、存储空间、端口占用是有明确要求的。我吃过几次亏之后,总结了一套固定检查项,每台新机器先过一遍再动手。
2.1 Ubuntu 版本与基础依赖
Harbor v2.5.0 我当时跑得最多的是 Ubuntu 20.04 LTS,18.04 也能跑,22.04 也试过,问题都不大。Ubuntu 版本反而不是主要矛盾,真正容易出问题的是 Docker 版本太老。
基础依赖我一般只装几个:tar(解压必需)、curl(排查用)、openssl(后面生成 https 证书必须)。命令很简单:
sudo apt update sudo apt install -y tar curl opensslopenssl 这里多说一句,Ubuntu 20.04 自带的 OpenSSL 1.1.1 足够用了,生成证书、查看证书都方便。如果哪天遇到 openssl 命令参数行为诡异,先确认不是系统里残留了太老的版本。
2.2 Docker 和 Docker Compose 的安装与验证
Docker 我建议直接用官方源装,Ubuntu 下的安装方式已经非常成熟:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin如果是在完全离线的环境里装 Docker,那就需要提前把 docker-ce 相关的 deb 包整体拷贝进去,用dpkg -i或apt install ./xxx.deb装。装完之后,最重要的验证是 compose 插件可用:
docker version --format '{{.Server.Version}}' docker compose version没有docker compose命令时,传统 standalone 的docker-compose也可以,Harbor 的install.sh会自己判断。但不管用哪个,版本都不能太老,Compose v2 最好,v1 的 1.29+ 也行。
2.3 存储空间、端口和网络规划
存储规划这一块,我建议提前做,别等装完再后悔。Docker 的数据目录/var/lib/docker和 Harbor 的数据目录(默认/data)都要预留足够空间。离线包里镜像 tar 大概 1GB 左右,导入之后占用的实际磁盘空间会更可观,建议 Docker 数据目录预留 20GB 以上,Harbor 的data_volume预留 100GB 以上——镜像仓库这种东西,后面数据涨幅是很快的。
端口方面主要看 80 和 443。Harbor 默认对外入口就是这两个端口,如果机器上已经跑了 nginx 或者其他 Web 服务,要提前把端口错开,不然install.sh起来后就会看到端口冲突的错误。我一般习惯先用ss -lntp看一眼监听情况,再决定要不要调整 harbor.yml 里的端口配置。
3. 在 Ubuntu 上直装 Harbor 的完整流程
环境弄好之后,安装本身其实很简单,但每一步都有一个"为什么"。我按实操顺序把完整流程走一遍,重点讲那些官方文档没说透的细节。
3.1 校验、解压、生成配置文件
拿到harbor-offline-installer-v2.5.0-rc1.tgz后的第一步,我建议先做完整性校验。离线包在传输过程中损坏的概率不高,但一旦损坏,docker load到一半报错,排查起来非常浪费时间。用 md5sum 或 sha256sum 都行:
md5sum harbor-offline-installer-v2.5.0-rc1.tgz校验值对上之后解压,进入目录,把模板复制成真正的配置:
tar -xzf harbor-offline-installer-v2.5.0-rc1.tgz cd harbor cp harbor.yml.tmpl harbor.ymlharbor.yml是 Harbor 唯一的配置入口,install.sh和prepare都会以它为准,所以值得多花几分钟逐项看清楚。后面改配置、改端口、改密码,都是改这个文件。
3.2 harbor.yml 关键参数解析
我第一次部署时对这些参数没什么概念,后来才发现有些坑是写死在默认值里的。现在我把关键参数整理成一张表,方便对着改。
| 参数 | 作用 | 我的建议 |
|---|---|---|
| hostname | 对外暴露的地址,docker login 时要用它 | 填能解析到本机的域名,或内网 IP |
| http.port | http 监听端口 | 默认 80,被占用就改 |
| https.port | https 监听端口 | 启用 https 后建议用 443 |
| https.certificate / private_key | 服务端证书与私钥路径 | 后面专门讲如何生成 |
| harbor_admin_password | 管理员初始密码 | 一定要改,别用默认的 Harbor12345 |
| database.password | 数据库 root 密码 | 启动后改很麻烦,第一次就设好 |
| data_volume | 持久化数据目录 | 放到大分区或独立数据盘 |
关于 hostname 有个容易踩的坑:后续docker login的地址必须和 hostname 保持一致。如果你填的是本机 IP,后面就用这个 IP 登录;如果你填的是域名,那证书和登录都要用域名。我第一次部署时图省事填了hostname: 127.0.0.1,结果其他节点根本没法用这个仓库,只能全部重新来一遍。
3.3 执行 install.sh 安装
基础安装直接跑:
sudo ./install.sh执行过程中 install.sh 会先调用docker load导入harbor.v2.5.0.tar.gz里的所有镜像,然后运行prepare生成 nginx 配置和 docker-compose.yml,最后docker compose up -d启动全部组件。如果想让漏洞扫描功能可用,可以带上 Trivy 参数:
sudo ./install.sh --with-trivy如果你是从老版本(比如 2.2、2.3)升上来的,注意 v2.5.0 开始官方安装脚本的可选组件已经变了,Clair 和 ChartMuseum 在新版本里逐渐退出,扫描器以 Trivy 为主。这种变化直接看install.sh --help的输出就行,别拿老版本的肌肉记忆去加参数,加了反而会报错。
安装完成后,验证服务状态:
docker compose ps curl -k http://127.0.0.1/api/v2.0/health返回 healthy 或者版本信息就说明服务正常。浏览器打开http://<hostname>输入管理员账号,第一次登录系统会强制要求修改初始密码,这个设计还是很好的。
4. 从 http 改成 https,绕不开的那几步
如果只在局域网里自己用,http 似乎也行。但一旦要接 Kubernetes 集群、要让其他开发机都来拉镜像,或者面对内网安全审计,http 就成了绕不开的坎。
4.1 为什么我建议仓库直接上 https
理由有很多,我讲几个实际层面的。
第一,镜像仓库里存的是公司核心业务代码和运行配置,明文传输等于把账本贴在门外面,抓包工具一扫,镜像内容、访问凭证全暴露了。第二,Kubernetes 节点如果配置 http 镜像源,每个节点都要设置 insecure-registries,还要忍受跳过 TLS 校验带来的各种诡异问题;统一改成 https,所有节点只要信任同一个 CA,客户端配置干净利落。第三,很多安全基线扫描现在都把 TLS 作为硬性要求,仓库开着 http 连验收都过不了。
4.2 用 openssl 生成自签名 CA 与服务端证书
生成证书的过程我拆成两层:一个是根 CA,一个是 Harbor 自己的服务端证书。正规做法是让内部 CA 体系签发,但在实验室或小团队场景里,自建 CA 然后签 Harbor 证书,完全够用,而且全程可控。
第一步,生成 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第二步,生成 Harbor 服务端私钥:
openssl genrsa -out harbor.key 2048这一步是很多人翻车的地方。直接openssl req -new -x509生成的证书没有 SAN 字段,Chrome 会拦截访问,docker 和 containerd 也会报 x509 错误。所以签发证书必须带 subjectAltName。新建一个harbor-san.cnf,内容类似:
[req] distinguished_name = dn req_extensions = ext [dn] CN = harbor.example.com [ext] subjectAltName = @alt_names [alt_names] DNS.1 = harbor.example.com DNS.2 = localhost IP.1 = 192.168.1.10alt_names这一段务必覆盖所有实际访问入口。如果你有多个内网 IP,或者计划用域名访问,把 IP 和域名都列进去。然后用这个配置签发证书:
openssl req -new -key harbor.key -out harbor.csr -config harbor-san.cnf openssl x509 -req -in harbor.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 825 -sha256 -extfile harbor-san.cnf -extensions ext -out harbor.crt生成的harbor.crt和harbor.key就是后面 harbor.yml 里要引用的文件。证书有效期我习惯给 825 天,约等于两年多,既符合常见安全策略,也不需要频繁续期。
4.3 修改 harbor.yml 并安全重启服务
把证书放到固定目录,我习惯放在/data/certs下,权限要收好:
sudo mkdir -p /data/certs sudo cp harbor.crt harbor.key ca.crt /data/certs/ sudo chown -R root:root /data/certs sudo chmod 640 /data/certs/*修改 harbor.yml:
hostname: harbor.example.com http: port: 80 https: port: 443 certificate: /data/certs/harbor.crt private_key: /data/certs/harbor.key注意这里有个设计取舍。如果同时保留http.port和https.port,Harbor 的 nginx 入口会同时监听 80 和 443,两种方式都能访问。我建议尽早只暴露 https,把 http 部分注释掉,或者把 http.port 改成一个内网调试端口。否则业务方一直在走明文,等你想关 http 时又要全局通知一遍,反而更麻烦。
接下来是很多人都会犯的错:修改完 harbor.yml 后直接docker compose down && docker compose up -d,发现 https 根本不生效。原因是 Harbor 的 nginx 配置和 docker-compose.yml 都由prepare脚本在 install 阶段生成,配置文件改了不重新跑 prepare,nginx 根本不会加载新证书。最稳妥的做法是直接再跑一次 install.sh:
cd ~/harbor sudo ./install.sh --with-trivyinstall.sh 会检测到本地镜像已存在,docker load很快就能跳过,prepare 在启动前重新生成整套配置,整个流程非常安全。启动完成后,浏览器访问https://harbor.example.com验证证书是否生效。
4.4 客户端如何信任这个 CA
服务端配好了,客户端如果不信任 CA,docker login依然报错。这里要区分两种情况。
docker 客户端(Debian/Ubuntu)需要在/etc/docker/certs.d/下建立以 hostname 命名的目录,并把 ca.crt 放进去:
sudo mkdir -p /etc/docker/certs.d/harbor.example.com sudo cp /data/certs/ca.crt /etc/docker/certs.d/harbor.example.com/ sudo systemctl restart docker docker login harbor.example.comcontainerd 作为 Kubernetes 节点的运行时,则是在/etc/containerd/certs.d/或 config.toml 里配置 ca_file。以 containerd 为例:
[plugins."io.containerd.grpc.v1.cri".registry] [plugins."io.containerd.grpc.v1.cri".registry.configs] [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.example.com"] [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.example.com".tls] ca_file = "/etc/containerd/certs.d/harbor.example.com/ca.crt"把 ca.crt 放到对应位置,重启 containerd,kubelet 就能正常从 Harbor 拉取镜像了。这里有个常见的误区:有人把 ca.crt 丢到系统级的/etc/ssl/certs,重启 docker 后还是失败。因为 docker 守护进程默认不读系统 CA 证书库,它认的是/etc/docker/certs.d/这套独立的逻辑,必须按 docker 自己的规则来。
5. 部署和改造过程中遇到的几个典型问题
整个流程走下来,总会遇到几个经典问题。我把高频的和几个特有场景整理成速查表:
| 现象 | 常见原因 | 解决思路 |
|---|---|---|
| install.sh 阶段 docker load 失败 | /var/lib/docker所在分区满了 | 用 df -h 确认空间,清理镜像或扩容 |
| 80/443 端口启动失败 | 端口被已有服务占用 | ss -lntp 排查,改端口或停冲突服务 |
| docker login 报 x509 证书错误 | ca.crt 未正确配置,或证书缺 IP SAN | 放对 certs.d 路径,重新签带 SAN 的证书 |
| 页面显示 502 | postgres/redis 初始化较慢 | 等待启动完成,用 docker compose logs 观察 |
| 修改配置后不生效 | 没有重新执行 prepare | 重跑 install.sh,或显式执行 prepare |
| 忘记管理员密码 | 密码修改后未及时记录 | 进 PostgreSQL 重置,或从备份恢复 |
展开讲两个真实案例。
第一个是磁盘空间问题。有次在一个内网环境部署,install.sh 停在 loading image 阶段很长时间,最后直接报 no space left on device。排查了很久才发现/var/lib/docker挂在根分区上,根分区只剩不到 2GB,而离线包里的镜像加起来有好几个 GB。解决方法是把 docker 的 style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />