阶段二 · Docker 工程实践

Docker Hub / Harbor / 企业级镜像管理

前置回顾

第 05 篇讲过:Registry 是镜像的存储和分发中心,推拉按层传输
第 06 篇讲过:好的 Dockerfile 产出小而安全的镜像

但镜像构建出来之后怎么办?谁来存,谁可以拉,有没有漏洞?这就是本篇要解决的问题.

回顾:Registry 解决了什么问题

先快速回顾第 05 篇的核心模型:

docker build → docker tag → docker push → Registry → docker pull → docker run

└── 本篇聚焦这里

Registry 不光是一个"存镜像的地方".在企业级场景中它还要回答:

问题 Registry 要做什么
谁能 push?谁能 pull? 认证 + 权限控制(RBAC)
镜像里有漏洞吗? 自动漏洞扫描(CVE 检测)
怎么同步到另一个机房? 镜像复制(Replication)
磁盘被旧镜像占满了? 垃圾回收(GC)+ 保留策略
能不能对外网不暴露? 私有部署,HTTPS + 自签证书

Docker Hub

官方镜像与认证

Docker Hub 上最特殊的一批镜像叫 Docker Official Images--由 Docker 公司和相关社区维护,经过审核才发布.在前几篇用的 nginx,postgres,redis,alpine 都在这个名单里.

如何区分仓库里谁的镜像可信?

# Docker Hub 上的三种身份标识
nginx ← Docker Official Image(官方维护,名字不带用户名前缀)
library/nginx ← 和上面是同一个,library 是官方镜像的隐式命名空间
mycompany/nginx ← Verified Publisher(企业认证发布者,有蓝色对勾)
randomuser/nginx ← 社区镜像(任何人都能上传,需谨慎使用)

不要看到 nginx 名字就放心--只有不带用户名前缀的那个才是官方的.someuser/nginx 是社区用户随便传的,可能是恶意镜像.

免费版的限制

免费版 付费版(Pro / Team)
私有仓库 1 个 无限
Pull 频率 每 6 小时 100 次(匿名)/ 200 次(登录) 5000 次/天 起
存储空间 无限制(公共仓库) 无限制
漏洞扫描 有限(仅官方镜像的部分 tag) 完整 Snyk 扫描
团队协作 RBAC + 审计日志

Rate Limiting 的影响

免费匿名用户每 6 小时只能 pull 100 次.

如果你的 CI 流水线每次 push 代码都从 Docker Hub 拉基础镜像,10 个开发者一天推 30 次代码 = 300 次 pull → 很快就会触发限流,CI 报错 toomanyrequests.

解决方案:登录后 pull(200 次/6h),部署本地缓存 Registry(pull-through cache),或者换用云厂商的镜像源.

为什么企业需要私有 Registry

用 Docker Hub 够了吗?对于个人项目和小团队,够.但以下几件事 Docker Hub 免费版做不到:

企业需求 Docker Hub 免费版能做到? 为什么做不到
镜像不经过公网 Docker Hub 在公网上,敏感业务的镜像不能传到外部服务器
谁 push 了生产镜像? 没有操作审计日志
这个镜像有 CVE 吗? 没有主动扫描机制(免费版扫不了私有仓库)
深圳和新加坡的集群用同一份镜像 没有跨区域复制,每个集群各自从 Docker Hub 拉
镜像保留 30 天自动清理 没有保留策略和垃圾回收

Harbor 企业级 Registry

Harbor(读作 "哈勃")是 CNCF 毕业项目(和 Kubernetes 同级),目前企业私有 Registry 的事实标准.它本质上是给开源 Docker Registry 加了一层完整的企业功能外壳.

架构概览

┌────────────────────────────┐
│ Harbor │
├────────────────────────────┤
│ • direction TB │
│ • Portal (Web UI) │
│ • API Server │
│ • Auth (OIDC) │
│ • Notary (签名) │
│ • Core (配置管理) │
│ • Registry (镜像存储) │
│ • Trivy (漏洞扫描) │
│ • PostgreSQL (元数据库) │
│ • Redis (缓存) │
│ • Job Service (异步任务) │
│ • API --> Core │
│ • Core --> Reg │
│ • Core --> Trivy │
│ • Core --> PG │
└────────────────────────────┘

各组件职责(别被数量吓到--它们都是有原因才拆出来的):

组件 做什么 为什么单独
Core 配置管理中枢,管理项目/用户/权限/复制策略 业务逻辑集中,其他组件各司其职
Registry 就是开源 Docker Registry--存镜像,接收 push/pull Harbor 是它的壳,不改 Registry 本身的代码
Trivy 扫描镜像每一层,查已知 CVE 漏洞 独立服务,可替换为其他扫描器(Clair,Snyk)
PostgreSQL 存项目,用户,权限,扫描结果等元数据 镜像本身在 Registry 存,这些"关于镜像的信息"在 DB 存
Redis 缓存用户 session,API 限流计数 -
Job Service 跑异步任务:镜像复制,垃圾回收,触发扫描 耗时操作不阻塞 API,走任务队列
Portal Web UI(浏览器里操作 Harbor 的界面) 和 API 分离,可以禁用只用 API/CLI

Harbor = 仓库管理系统 + 开源 Docker Registry.
Docker Registry 就是仓库里的一排排货架(存镜像数据),Harbor 是门禁系统 + 摄像头 + 质检员 + 登记表--它不代替货架,但让整个仓库变得安全,可管理.

RBAC 权限模型

Harbor 的权限体系分三层:系统级项目级仓库级.

系统级(整个 Harbor 实例):
├─ 系统管理员 → 可以创建项目,管理用户,配置全局设置
└─ 匿名用户 → 只能访问设为"公开"的项目

项目级(每个 Project 内):
├─ 项目管理员 → 管理该项目内的成员和配置
├─ 维护者 → 可以 push / pull / 删除镜像 / 配置复制策略
├─ 开发者 → 可以 push / pull(不能做管理操作)
└─ 访客 → 只能 pull

典型企业配置:
Project: backend(后端服务)
├─ 张三 → 维护者(可以发布新版本)
├─ 李四 → 开发者(日常 push)
└─ CI 机器人 → 开发者(CI 流水线 push 用)

Project: frontend(前端服务)
├─ 王五 → 项目管理员
└─ CI 机器人 → 开发者

→ 前端团队看不到后端项目的镜像,后端也看不到前端的
→ 都在同一个 Harbor 实例上,通过 RBAC 隔离开

对接企业账号(LDAP / OIDC)

# 不用每个开发者在 Harbor 里再注册一遍账号
# Harbor 可以直接对接公司现有的账号体系:

公司 LDAP / AD → Harbor 直接从域控同步用户和分组
OIDC(如 Keycloak / Okta)→ 单点登录,浏览器打开 Harbor 自动跳公司登录页

# 然后权限配置直接用 LDAP 的分组:
# "backend-team" 这个 LDAP 组的成员 → 自动获得 backend 项目的开发者权限

漏洞扫描

回顾第 06 篇:镜像由多层组成,每一层可能包含有漏洞的系统库.Harbor 用 Trivy 扫描每一层:

Trivy 怎么工作:

1. 拿到一个镜像(如 myapp:v1.0)
2. 解包每一层 → 提取出所有安装的软件包和版本号
3. 和 CVE 数据库比对(CVE = Common Vulnerabilities and Exposures,公共漏洞库)
→ libssl 版本 1.1.1k → 查 CVE 数据库 → CVE-2023-XXXX:高危!
→ openssl 版本 3.0.7 → 查 CVE 数据库 → CVE-2024-YYYY:严重!
4. 生成报告

Harbor 的可配置策略:
• 自动扫描:每次 push 新镜像自动触发
• 阻断策略:包含"严重"漏洞的镜像阻止部署(无法 pull)
• 白名单:某些 CVE 已知不影响你的业务,可以忽略
# 在 Harbor 项目设置里配置漏洞策略(概念示意)
vulnerability_policy:
on_push: auto_scan # 每次 push 自动扫描
prevent_pull:
severity: critical # 有"严重"漏洞的镜像不能 pull
allowlist:
- CVE-2024-0001 # 这个漏洞我们知道,不影响我们,放行
- CVE-2024-0002

镜像复制:跨数据中心同步

这是 Harbor 最有价值的特性之一.多个 Harbor 实例之间可以自动同步镜像--不需要手动在每个机房 push 一遍.

场景:你的公司在深圳和新加坡各有一个数据中心
两个集群都需要跑同一个 myapp:v1.0 镜像

不用复制(低效):
深圳 CI → push 到深圳 Harbor → 深圳 K8s pull
新加坡 CI → 重新 build → push 到新加坡 Harbor → 新加坡 K8s pull
(两个地方各 build 一次,无法保证两次构建完全一致)

用复制(高效):
深圳 CI → build & push 到深圳 Harbor
→ Harbor 自动复制到新加坡 Harbor
→ 新加坡 K8s pull
(只 build 一次,Harbor 保证两边是同一个 digest 的镜像)
复制的两种模式:

Push 模式:深圳 Harbor 主动推到新加坡
┌─ 深圳 Harbor ─┐ ─── push ───→ ┌─ 新加坡 Harbor ─┐
└──────────────┘ └──────────────┘

Pull 模式:新加坡 Harbor 主动从深圳拉
┌─ 深圳 Harbor ─┐ ←── pull ─── ┌─ 新加坡 Harbor ─┐
└──────────────┘ └──────────────┘

复制触发方式:
• 事件驱动:每次 push 新镜像自动复制
• 定时:每天早上 8 点同步一次
• 手动:在 UI 里点"立即同步"

复制过滤器:
• 只复制标签匹配 release-* 的镜像(不复制 dev-* 的)
• 只复制仓库名为 backend/* 的(不复制 frontend/* 的)

云厂商 Registry

如果你用云(AWS / 阿里云 / 腾讯云),通常不需要自己搭 Harbor--各云都有托管版的 Registry.选择标准很简单:

Registry 优势 劣势
Harbor 自建 完全控制,无额外费用,功能最全 需要自己搭,自己维护,自己升级
云厂商托管 零维护,和云上其他服务深度集成(IAM 权限,VPC 内网免流量费) 花钱(存储+流量),功能不如 Harbor 丰富,换云需要迁移

选择建议:公司有运维团队 → Harbor 自建;小团队全在某一朵云上 → 用云的托管版;生产 Harbor + 云托管做镜像复制 → 双保险.

实践:5 分钟自建 Harbor

Harbor 官方提供了一套 Compose 文件,一键部署(注意--这和 07 篇学的完全对应,Harbor 自己就是用 Compose 跑的):

# 1. 下载 Harbor 安装包(选择 offline 版本,自带所有镜像)
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
tar xzf harbor-offline-installer-v2.10.0.tgz
cd harbor

# 2. 复制配置模板
cp harbor.yml.tmpl harbor.yml

# 3. 编辑 harbor.yml(最小配置)
# hostname: harbor.local ← 改成你的域名或 IP
# harbor_admin_password: xxxx
# 如果不用 HTTPS 先注释掉 https 部分,用 http

# 4. 安装并启动(本质就是 docker compose up -d)
sudo ./install.sh
# Harbor 会用 Compose 启动所有组件(nginx/proxy + core + registry + trivy + ...)

# 5. 浏览器打开 http://harbor.local
# 用户名 admin,密码你设的那个

# 6. 在 Harbor UI 里创建一个项目,然后配置本地 Docker
docker login harbor.local
# 按提示输入 admin / 密码

# 7. 推送镜像
docker tag myapp:v1 harbor.local/myproject/myapp:v1
docker push harbor.local/myproject/myapp:v1

学习用:Harbor 也可以用 Compose 一键起

Harbor 的 install.sh 做的事情无非就是:生成 docker-compose.ymldocker compose up -d.
可以去 harbor/ 目录下翻 docker-compose.yml,会看到 07 篇学到的所有东西:services,networks,volumes,healthcheck,depends_on--全部用上了.

小结

本篇要点回顾

要点 一句话概括
Docker Hub 官方镜像 没有用户名前缀的才是官方镜像(nginx),xxx/nginx 是社区上传的,需谨慎
Docker Hub 限流 免费匿名每 6h 只 100 pull,CI 密集使用会触发 toomanyrequests
为什么私有 Registry 不经过公网,有审计日志,可主动扫漏洞,可跨机房同步,可设保留策略
Harbor 架构 Core(配置) + Registry(存镜像) + Trivy(扫漏洞) + PostgreSQL + Redis + Job Service
Harbor RBAC 系统级 → 项目级(管理员/维护者/开发者/访客)→ 可对接公司 LDAP/OIDC 账号
漏洞扫描 Trivy 解包每层 → 提取软件包版本 → 和 CVE 数据库比对 → 可配置阻断策略(有严重漏洞禁止 pull)
镜像复制 推模式 / 拉模式,事件驱动或定时,支持按 tag/仓库名过滤--多数据中心自动同步
部署方式 Harbor 自己就用 Compose 部署(你在 07 篇学的全部技能在此刻闭环)

动手练习

  1. 在 Docker Hub 注册账号,把 06 篇或 07 篇写的镜像推上去.然后换一台机器(或删掉本地镜像后)docker pull 回来运行
  2. docker logout 退出登录,然后跑 docker pull 几次,感受一下限流的实际体验(如果触发了的话)
  3. 用 Compose 在本地部署 Harbor(根据上面实践小节的步骤),创建两个项目,给不同项目设置不同的成员权限,验证权限隔离生效
  4. 在 Harbor 里开启自动扫描,push 一个老旧镜像(比如 node:10),观察 Trivy 的扫描结果
  5. 思考题:为什么 Harbor 自己要用 Compose 来部署?如果 Harbor 的容器都停了,镜像数据还在吗?(提示:回顾 07 篇的 Volume)