团队开始自己构建 Docker 镜像后,最容易被低估的不是 docker build,而是镜像放哪儿。把所有镜像推到个人 Docker Hub 账号,权限、限流、离职交接和私有仓库费用很快就会变成麻烦;直接在 VPS 上跑一个裸 registry:2 虽然轻量,但缺少项目权限、漏洞扫描、审计日志和清理策略。
Harbor 更像一套完整的企业镜像仓库。它在 OCI Registry 外面补上 Web 管理、项目级 RBAC、Robot Account、Trivy 漏洞扫描、镜像保留、垃圾回收和复制策略。代价也很直接:组件多、磁盘增长快,备份和升级不能只复制一份 Compose 文件。
本文以 Harbor v2.15.2、Ubuntu 24.04、Docker Compose、Let’s Encrypt HTTPS 和 Trivy 为基准,在一台 VPS 上搭建可供 Jenkins、GitHub Actions、GitLab Runner 或开发机使用的私有 Docker 镜像仓库。版本按 2026 年 9 月 3 日 Harbor 官方发布页核对;实际部署前仍要检查最新补丁版本与安全公告。
Harbor 不是所有项目都需要。如果只有一台机器、几个镜像,而且不需要多人权限,普通 Docker Registry 配合 HTTPS 和 Basic Auth 会省很多内存。
下面这些情况更适合 Harbor:
- 多个团队或项目需要彼此隔离的私有镜像仓库;
- CI 只允许推送指定项目,生产机只允许拉取;
- 镜像推送后要自动做 CVE 扫描;
- 需要保留
release-*,自动淘汰过期开发 tag; - 需要审计谁推送、删除或拉取了镜像;
- 后续可能把镜像复制到另一机房或云 Registry。
| 方案 | 资源占用 | 权限与审计 | 漏洞扫描 | 适合场景 |
|---|---|---|---|---|
| Docker Registry | 低 | 需要自行组合 | 无内置扫描 | 单人、小规模镜像缓存 |
| Harbor | 中高 | 项目、角色、Robot Account | 可集成 Trivy | 团队、自托管 CI/CD、合规需求 |
| GitLab Container Registry | 随 GitLab 一起维护 | 与 GitLab 项目统一 | 取决于 GitLab 版本和功能 | 已经完整使用 GitLab |
| 云厂商 Registry | 无需维护服务端 | 由云平台管理 | 通常按套餐提供 | 接受云绑定和流量费用 |
如果代码和 CI 已经全部放在 GitLab,GitLab CE 自带 Registry 与 Runner通常更省事。Harbor 的价值在于它不绑定某一种 Git 平台,可以同时服务 Jenkins、GitHub Actions、GitLab 和 Kubernetes。
Harbor 官方给出的最低配置是 2 核 CPU、4GB 内存、40GB 磁盘,推荐配置是 4 核、8GB 内存、160GB 磁盘。开启 Trivy 后还会下载漏洞数据库并在扫描时消耗 CPU、内存与磁盘 IO。
实际选型可以从下面的规格起步:
| 用途 | 建议配置 | 说明 |
|---|---|---|
| 测试与个人项目 | 2 vCPU、4GB、80GB SSD | 限制并发扫描,不保存大量历史 tag |
| 3–10 人团队 | 4 vCPU、8GB、160GB SSD | Harbor 与 Trivy 同机,设置保留策略 |
| 多项目或高频 CI | 8 vCPU、16GB、独立数据盘 | 数据盘至少预留一轮完整备份空间 |
| 跨机房生产 | 独立数据库、对象存储或多实例 | 不再属于单 VPS 教程范围 |
Harbor 的磁盘不能只按镜像最终大小计算。同一镜像的层可以复用,但构建缓存、多个架构、旧 tag、扫描数据库、PostgreSQL、Job 日志和备份都会占空间。准备 100GB 镜像数据时,160GB 系统盘通常不够从容地做本地备份和升级迁移。
建议把 /data 放在独立 SSD 或块存储卷上。扩容前先确认 VPS 提供商是否支持在线扩盘,以及快照是否包含这块数据盘。
准备一个只给 Registry 使用的域名,例如 harbor.example.com,创建 A 记录指向 VPS。IPv6 没配置好时不要添加 AAAA 记录,否则部分 Docker Client 会优先连接错误地址。
需要开放的端口很少:
| 端口 | 用途 | 建议 |
|---|---|---|
22/TCP | SSH 管理 | 密钥登录并限制管理来源 |
80/TCP | Let’s Encrypt HTTP-01 验证、HTTP 跳转 | 对公网开放 |
443/TCP | Harbor Portal、API、Docker Push/Pull | 对使用者开放 |
不要把 Harbor 内部的 PostgreSQL、Redis、Registry 或 Jobservice 端口单独暴露到公网。安装器生成的 Compose 会让这些组件走内部 Docker Network。
如果出现“Portal 能打开但 Docker 登录超时”,按端口、防火墙、安全组与监听地址排查指南从 DNS、VPS 防火墙、云安全组和监听端口逐层检查。
下面假设 Docker Engine 和 Compose Plugin 已经按 Docker 官方仓库安装。不要混用旧的 Python docker-compose 与新版 docker compose。
sudo apt update
sudo apt full-upgrade -y
sudo apt install -y ca-certificates curl gnupg jq certbot dnsutils
docker version
docker compose version
openssl version
Harbor 官方要求 Docker Engine 高于 20.10、Docker Compose 高于 2.3。生产环境还要配置日志轮转、磁盘告警与资源边界,可以对照Docker Compose 生产环境清单补齐宿主机设置。
先确认域名已经解析到当前 VPS:
dig +short harbor.example.com A
curl -4 ifconfig.me
两边 IP 一致后,用 Certbot Standalone 申请证书。此时 80 端口不能被其他服务占用:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo certbot certonly --standalone \
-d harbor.example.com \
--agree-tos \
-m [email protected] \
--no-eff-email
把邮箱和域名换成真实值。证书默认位于:
/etc/letsencrypt/live/harbor.example.com/fullchain.pem
/etc/letsencrypt/live/harbor.example.com/privkey.pem
Harbor 官方建议生产环境使用可信 CA 签发的证书。不要为了省一步,把公开 Registry 配成 HTTP 再让每台客户端添加 insecure-registries。
把安装器固定在 /opt/harbor,不要下载到临时目录后就删掉。升级、重新生成配置和故障恢复都会用到它。
cd /tmp
HARBOR_VERSION=v2.15.2
curl -fLO \
"https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-online-installer-${HARBOR_VERSION}.tgz"
curl -fLO \
"https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-online-installer-${HARBOR_VERSION}.tgz.asc"
按 Harbor 官方文档导入发布签名密钥并验证安装包:
gpg --keyserver hkps://keyserver.ubuntu.com \
--receive-keys 644FF454C0B4115C
gpg --verify \
"harbor-online-installer-${HARBOR_VERSION}.tgz.asc" \
"harbor-online-installer-${HARBOR_VERSION}.tgz"
看到有效签名后再解压。第一次安装时确认目标目录不存在:
sudo tar -xzf "harbor-online-installer-${HARBOR_VERSION}.tgz" -C /opt
sudo chown -R root:root /opt/harbor
cd /opt/harbor
ls -la
在线安装器本身很小,执行安装时才从镜像仓库下载 Harbor 组件。受限网络或需要离线安装时,应从同一 Release 下载体积更大的 Offline Installer。
Harbor 的 Nginx 容器需要读取证书。把证书复制到固定数据目录,避免直接依赖 Certbot 的软链接结构:
sudo install -d -m 700 /data/cert
sudo cp \
/etc/letsencrypt/live/harbor.example.com/fullchain.pem \
/data/cert/harbor.crt
sudo cp \
/etc/letsencrypt/live/harbor.example.com/privkey.pem \
/data/cert/harbor.key
sudo chmod 600 /data/cert/harbor.crt /data/cert/harbor.key
生成两个不同的随机密码:
openssl rand -base64 32
openssl rand -base64 32
一个用于初始 admin,另一个用于 Harbor 内置 PostgreSQL。不要在示例文件里保留 Harbor12345,也不要让两个密码相同。
复制模板并限制权限:
cd /opt/harbor
sudo cp harbor.yml.tmpl harbor.yml
sudo chmod 600 harbor.yml
sudoedit harbor.yml
至少修改下面这些字段。未列出的配置保留 v2.15.2 模板默认值,不要拿旧版本博客的整份 harbor.yml 覆盖新模板。
hostname: harbor.example.com
http:
port: 80
https:
port: 443
certificate: /data/cert/harbor.crt
private_key: /data/cert/harbor.key
harbor_admin_password: 替换为第一段随机密码
database:
password: 替换为第二段随机密码
data_volume: /data
trivy:
ignore_unfixed: false
skip_update: false
offline_scan: false
insecure: false
log:
level: info
local:
rotate_count: 10
rotate_size: 200M
location: /var/log/harbor
几点不要照抄错:
hostname只写域名,不加https://;certificate和private_key是宿主机绝对路径;data_volume放 Registry、数据库、Redis、Trivy 等持久数据;skip_update: false允许 Trivy 更新漏洞库;- 密码如果含特殊字符,要以当前模板注释和 YAML 解析结果为准。
检查文件中是否还留着默认密码:
sudo grep -nE 'Harbor12345|root123' /opt/harbor/harbor.yml
正常情况下不应输出匹配。不要把 harbor.yml 提交到公开 Git 仓库,它包含数据库和初始管理员密码。
先确认 80、443 没有被 Nginx、Caddy 或 Apache 占用:
sudo ss -lntp | grep -E ':(80|443)\b' || true
如果同一台 VPS 已经运行其他 Web 服务,不能直接启动这套配置。要么给 Harbor 独立 IP/VPS,要么设计统一反向代理和 external_url;不要让两个服务抢相同端口。
执行安装:
cd /opt/harbor
sudo ./install.sh --with-trivy
--with-trivy 很关键。默认执行 install.sh 不会安装 Trivy,之后页面里自然也不会出现可用扫描器。
检查容器与 API:
cd /opt/harbor
sudo docker compose ps
curl -fsS https://harbor.example.com/api/v2.0/health | jq
curl -sSI https://harbor.example.com/v2/ | head
健康接口应返回 healthy。Registry 的 /v2/ 在未登录时返回 401 Unauthorized 反而是正常现象,说明 HTTPS、Registry 路由和认证挑战已经接通。
查看异常日志:
cd /opt/harbor
sudo docker compose logs --tail=200
sudo find /var/log/harbor -maxdepth 1 -type f -printf '%f\n' | sort
访问 https://harbor.example.com,使用用户名 admin 和 harbor.yml 中的初始密码登录。上线前完成:
- 把管理员密码保存到团队密码库;
- 关闭匿名创建用户,除非确实需要公开注册;
- 普通开发者只加入对应项目,不授予系统管理员;
- 创建私有项目,不要直接往默认
library堆所有镜像; - 设置项目配额,防止一个流水线吃满整块磁盘;
- 检查 Trivy Scanner 状态和漏洞数据库更新时间;
- 配置审计日志保留与外部告警。
Harbor 的项目权限不是装饰。Private Project 只有成员和获得授权的 Robot Account 才能拉取;Public Project 允许匿名拉取,不适合存放内部业务镜像。
在 Harbor 中进入 Projects → New Project,创建私有项目 demo。镜像在项目不存在时不能直接推送。
本地登录:
docker login harbor.example.com
测试推送:
docker pull alpine:3.22
docker tag alpine:3.22 harbor.example.com/demo/alpine:3.22
docker push harbor.example.com/demo/alpine:3.22
docker pull harbor.example.com/demo/alpine:3.22
路径必须包含项目名:
harbor.example.com/<project>/<repository>:<tag>
不要长期让 CI 使用管理员账号。个人电脑执行 docker login 后,凭据可能写入 ~/.docker/config.json;团队电脑应配置系统 Credential Helper,并控制该文件权限。
进入 Projects → demo → Configuration:
- 开启 Automatically scan images on push;
- 根据团队策略开启 Prevent vulnerable images from running;
- 设置阻断等级,例如
Critical; - 为已确认且暂时无法修复的 CVE 使用有期限的 Allowlist。
自动扫描会增加推送后的 CPU 和 IO。4GB VPS 同时跑多个扫描任务时,Portal 可能明显变慢,所以小机器不要把 CI 并发开太高。
“扫描通过”也不代表镜像绝对安全。Trivy 依赖漏洞数据库,新的 CVE 可能在镜像推送几天后才出现。除了 Push 时扫描,还应安排周期性 Scan All,并观察 Trivy 数据库更新是否失败。
阻断拉取前先用测试项目验证。直接对生产项目启用 Critical 阻断,可能让已有部署在下次扩容或重启时拉不到镜像。
Robot Account 是给流水线使用的非人账号。进入:
Projects → demo → Robot Accounts → New Robot Account
为构建流水线创建 ci-push,只授予 demo 项目需要的权限:
- Repository:Pull;
- Repository:Push;
- Artifact:Read;
- 如流水线需要主动触发扫描,再单独增加扫描权限。
设置 90 天或符合团队轮换周期的过期时间。创建后立即保存系统显示的用户名和 Secret;Secret 通常只完整显示一次。不要勾选所有权限,也不要为单项目流水线创建跨项目 System Robot。
CI 登录时使用 Harbor 实际生成的 Robot 用户名,不要手工猜前缀:
printf '%s' "$HARBOR_ROBOT_SECRET" | \
docker login harbor.example.com \
--username "$HARBOR_ROBOT_USER" \
--password-stdin
完成 Push 后可以退出登录:
docker logout harbor.example.com
刚搭好的 Jenkins 可以把 Robot Account 存为 Username with password Credential,然后在 Jenkinsfile 中使用:
pipeline {
agent { label 'linux' }
environment {
REGISTRY = 'harbor.example.com'
IMAGE = 'harbor.example.com/demo/webapp'
}
stages {
stage('Build') {
steps {
sh 'docker build -t "$IMAGE:$BUILD_NUMBER" .'
}
}
stage('Push') {
steps {
withCredentials([usernamePassword(
credentialsId: 'harbor-demo-robot',
usernameVariable: 'HARBOR_USER',
passwordVariable: 'HARBOR_SECRET'
)]) {
sh '''
set +x
printf '%s' "$HARBOR_SECRET" | \
docker login "$REGISTRY" \
--username "$HARBOR_USER" \
--password-stdin
docker push "$IMAGE:$BUILD_NUMBER"
docker logout "$REGISTRY"
'''
}
}
}
}
}
这段 Pipeline 只演示认证和 Push。Docker 构建应放在隔离 Agent 上,不能因为要连接 Harbor 就把宿主机 Docker Socket 随手挂进 Controller。完整的 Controller、WebSocket Agent 和凭据隔离做法见Jenkins CI/CD 部署教程。
生产部署账号通常只需要 Pull,不应该复用 ci-push。建议为每个环境创建独立 Robot Account:
ci-push:构建并推送;staging-pull:只拉取测试环境镜像;prod-pull:只拉取生产镜像;- 每个账号使用不同过期时间与 Secret。
镜像 tag 删除和磁盘释放是两件事。先在 Projects → demo → Policy → Tag Retention 设计保留规则,例如:
- 永久保留所有
release-*; - 每个仓库保留最近 20 个
main-*; - 每个分支保留最近 5 个开发构建;
- 不要让可变的
latest成为唯一可回滚版本。
先执行 Dry Run,确认不会把仍在生产使用的 digest 删除。部署系统最好记录镜像 digest,而不是只记录 tag:
docker inspect \
--format='{{index .RepoDigests 0}}' \
harbor.example.com/demo/webapp:42
Tag Retention 负责选择保留或删除哪些 Artifact;它不是备份,也不能替代跨机房复制。
删除 tag 后,底层 Blob 不会马上释放空间。Harbor 需要 Garbage Collection 扫描没有被 Manifest 引用的 Blob。
进入 Administration → Clean Up → Garbage Collection:
- 先运行 DRY RUN;
- 查看预计回收的 Blob 与空间;
- 确认没有 Push、Retention 或复制任务异常;
- 再执行 GC Now 或设置每周计划;
- 检查 Garbage Collection History 和 Job 日志。
Harbor 会为最近上传的 Layer 保留安全时间窗口,官方当前说明为 2 小时。不要把 GC 当成磁盘满后的紧急按钮;磁盘接近 100% 时,数据库和 Registry 可能已经无法正常写入。
每周检查:
df -h
sudo du -xhd1 /data | sort -h
sudo du -xhd2 /data/registry | sort -h | tail -30
cd /opt/harbor && sudo docker compose ps
建议在磁盘使用率 70% 和 85% 设置两级告警,给 Retention、GC、扩盘和备份留出处理时间。
单机 Docker Compose 部署的核心数据在 data_volume,本文是 /data;安装配置在 /opt/harbor。只备份 /opt/harbor/docker-compose.yml 没用,镜像 Blob、数据库和项目配置都不在那里。
最容易验证的一致性备份方式是安排维护窗口,先把 Harbor 设置为 Read Only,等待 Push、扫描、复制和 GC 任务结束,再停止容器。
cd /opt/harbor
sudo docker compose ps
sudo docker compose down
停止后备份:
sudo install -d -m 700 /backup/harbor
sudo tar --xattrs --acls \
-C / \
-czf "/backup/harbor/harbor-$(date +%F-%H%M%S).tar.gz" \
data \
opt/harbor
sudo sha256sum /backup/harbor/harbor-*.tar.gz
如果 /data 很大,本地 tar 会占用双份磁盘,不适合长期使用。生产环境更适合文件系统/块存储快照,或用 restic 把停机后的 /data 和 /opt/harbor 直接发送到异机对象存储。可结合VPS 备份与恢复演练指南设置加密、保留和校验。
备份完成后启动并取消 Read Only:
cd /opt/harbor
sudo docker compose up -d
curl -fsS https://harbor.example.com/api/v2.0/health | jq
备份至少包含:
/data全部内容;/opt/harbor/harbor.yml和安装器;- 生成后的 Compose 与配置目录;
- TLS 证书或重新签发证书的流程;
- Harbor 版本、安装参数
--with-trivy; - Robot Account 重新签发和 CI 更新流程;
- Read Only 开关与恢复检查清单。
备份里含数据库密码、项目配置和镜像源码,必须加密并限制访问。不要把 Harbor 备份上传回同一台 Harbor 所依赖的唯一存储。
至少每季度在隔离 VPS 做一次恢复,而不是只检查压缩包能不能解开:
- 安装与备份一致的 Docker 和 Harbor 版本;
- 停止空 Harbor;
- 恢复
/data与/opt/harbor的所有者、权限和扩展属性; - 核对
harbor.yml的域名、证书路径与密码; - 运行
sudo ./prepare --with-trivy; - 执行
sudo docker compose up -d; - 验证 Portal、
/api/v2.0/health和/v2/; - 登录、拉取一张私有镜像并校验 digest;
- 检查项目、Robot Account、扫描结果、保留策略和审计日志;
- 记录恢复耗时和缺失项。
灾难恢复时不要顺便跨大版本升级。先用原版本恢复业务,再单独按官方迁移文档升级,排障边界会清楚很多。
本文用 Harbor 自带 Nginx 占用 80/443,所以 Certbot Standalone 续期需要维护窗口。先停 Harbor释放 80:
cd /opt/harbor
sudo docker compose down
sudo certbot renew --standalone
sudo cp \
/etc/letsencrypt/live/harbor.example.com/fullchain.pem \
/data/cert/harbor.crt
sudo cp \
/etc/letsencrypt/live/harbor.example.com/privkey.pem \
/data/cert/harbor.key
sudo chmod 600 /data/cert/harbor.crt /data/cert/harbor.key
sudo ./prepare --with-trivy
sudo docker compose up -d
确认新证书日期:
echo | openssl s_client \
-connect harbor.example.com:443 \
-servername harbor.example.com 2>/dev/null | \
openssl x509 -noout -issuer -dates
想避免续期停机,可以改用 DNS-01 验证或在独立反向代理上统一管理证书,但要按实际 DNS 提供商配置,不能盲目复制通用 Token。
Harbor 升级可能修改 harbor.yml 和数据库 Schema,不能只把镜像 tag 改成新版本。升级前:
- 阅读目标版本 Release Notes、兼容矩阵和迁移指南;
- 确认当前版本是否支持直接升级到目标版本;
- 完成
/data、数据库和安装目录备份; - 在备份副本上测试迁移与回滚;
- 记录 Trivy、外部存储、认证和复制配置;
- 安排明确维护窗口。
官方迁移流程的核心步骤是停止旧实例、备份安装目录和 /data/database、下载新安装器,再使用目标版本 goharbor/prepare:<tag> 迁移旧 harbor.yml。数据库 Schema 会在 Harbor Core 启动时迁移。
不要跳过官方不支持的中间版本,也不要假设数据库 Schema 能自动降级。真正的回滚依赖升级前的数据库和 /data 备份。
先检查 Harbor 是否提供完整证书链:
echo | openssl s_client \
-connect harbor.example.com:443 \
-servername harbor.example.com \
-showcerts
公有 Let’s Encrypt 证书出现这个错误,常见原因是 Harbor 配成了 cert.pem 而不是 fullchain.pem、客户端系统 CA 太旧,或域名实际连到另一台服务器。不要直接添加 insecure-registries 掩盖问题。
先确认 443 前面是否还有 CDN、WAF 或额外 Nginx。Harbor 自带 Nginx 之外的代理可能限制请求体或上传超时。绕过外层代理直连源站测试,再调整代理限制;不要只改 Harbor 容器里的临时配置,重新 prepare 后会被覆盖。
df -h
sudo du -sh /data/registry /data/database /data/trivy-adapter 2>/dev/null
cd /opt/harbor
sudo docker compose ps
sudo docker compose logs --tail=200 proxy core registry jobservice
重点检查磁盘满、inode 耗尽、代理超时、客户端到 VPS 的丢包,以及 Registry 是否能写入 /data/registry。
cd /opt/harbor
sudo docker compose logs --tail=200 trivy-adapter
date -Is
curl -I https://github.com
检查 VPS 出站网络、DNS、系统时间、代理配置和 GitHub 限流。离线环境要按官方流程准备离线漏洞库,不能简单设置 skip_update: true 后长期使用过期数据。
删除 tag 只移除引用,Blob 要等 Garbage Collection 才会回收。先运行 GC Dry Run,确认 Retention 已经执行、没有其他 Manifest 引用相同 Layer,再安排 GC。不要手工删除 /data/registry/docker/registry/v2/blobs。
检查账号是否过期、被禁用、Secret 是否轮换,以及 CI 使用的用户名是否包含 Harbor 实际生成的完整前缀。重新创建 Robot 后旧 Secret 不会自动更新到 Jenkins 或 GitHub Secrets。
cd /opt/harbor
sudo docker compose ps
sudo docker compose logs --tail=200
sudo journalctl -u docker --since '30 minutes ago' --no-pager
free -h
df -h
4GB 小机常见问题是 Trivy 扫描与数据库同时占用内存导致 OOM。先确认内核日志和容器退出码,再降低并发或升级内存,不要直接给所有容器加无限重启。
prepare 会根据 harbor.yml 重新生成 Compose 和组件配置。直接修改生成文件通常会被覆盖。能写进 harbor.yml 的设置都写回源配置;确实需要额外代理层时,把它作为独立、版本化的部署组件维护。
- Harbor 安装器版本固定为当前补丁版;
- 安装包签名已经验证;
- VPS 至少满足 2 核、4GB、40GB,生产环境留足磁盘;
-
/data位于可扩容、可快照的存储; - 域名 A/AAAA 记录与实际网络一致;
- Portal 和 Registry 使用可信 HTTPS;
-
harbor.yml不含默认密码,文件权限为600; - PostgreSQL、Redis 和 Registry 内部端口未暴露公网;
- 使用
--with-trivy安装,扫描器状态正常; - 项目默认为 Private,并设置容量配额;
- Push 后自动扫描策略已验证;
- 漏洞阻断阈值在测试项目验证过;
- CI 使用项目级 Robot Account,不用
admin; - Push 与生产 Pull 使用不同账号和权限;
- Robot Secret 有轮换和过期提醒;
- Tag Retention 已先做 Dry Run;
- Garbage Collection 有计划并检查历史结果;
- 70%/85% 磁盘告警已启用;
-
/data和/opt/harbor有加密异机备份; - 恢复演练能登录、拉取镜像并校验 digest;
- 证书续期流程已演练;
- 升级前会按官方支持路径备份和迁移。
官方最低配置是 2 核 CPU、4GB 内存和 40GB 磁盘,推荐 4 核、8GB、160GB。开启 Trivy、多人同时 Push 或保存多架构镜像时,4GB 很容易吃紧。小团队建议从 4 核、8GB 和独立 160GB SSD 起步。
Docker Registry 主要负责存取镜像,资源占用低;Harbor 增加 Web Portal、项目 RBAC、Robot Account、Trivy 扫描、审计、复制、Retention 和 GC。个人测试用 Registry 更轻,团队和 CI 权限管理更适合 Harbor。
公开或跨网络使用时必须配置 HTTPS。HTTP 需要客户端设置 insecure-registries,镜像凭据和流量也可能被中间人窃取。官方明确只把 HTTP 视为隔离测试环境的选择。
删除 Artifact 或 tag 只是移除引用,共享 Layer 也可能仍被其他 Manifest 使用。需要执行 Garbage Collection 才会删除无引用 Blob。先做 Dry Run,并确认生产镜像和保留规则没有被误删。
使用项目级 Robot Account,只授予目标项目的 Pull、Push 和必要读取权限,并设置过期时间。不要把 Harbor admin 密码放进 Jenkins。生产服务器再创建一个独立的只读 Robot Account。
不可以。Registry Blob 之外还需要 PostgreSQL 中的项目、权限、Artifact 元数据和策略,以及安装配置、证书和恢复步骤。单机部署至少要一致性备份完整 /data 与 /opt/harbor,并实际验证恢复。
- Harbor v2.15.2 发布页
- Harbor 安装前提与资源要求
- 下载 Harbor 安装器
- 配置 Harbor HTTPS
- 配置 harbor.yml
- 安装 Harbor 与 Trivy
- Harbor 项目与漏洞策略
- Harbor 漏洞扫描
- Harbor Garbage Collection
- Harbor 升级与数据迁移
Harbor 上线的标准不是 Portal 能打开,而是 CI 能用最小权限 Robot Account 推送、生产机只能拉取、扫描和 Retention 不会卡住交付、磁盘有持续告警,整套 /data 也能在另一台 VPS 恢复。先用 demo 项目跑通 Build、Push、Scan、Pull 和回滚,再把正式镜像迁进来。
