为什么需要私有 Docker 镜像仓库
前面的文章介绍了 Docker 镜像的构建、Tag 和 Push。实际开发中,镜像通常不会只保存在开发者本机,而是需要进入一个统一的镜像仓库。
一个典型的发布流程如下:
开发者
│
│ docker build
▼
本地 Docker Image
│
│ docker tag
▼
私有镜像仓库
│
├── 测试服务器
├── 生产服务器
├── CI/CD
└── Kubernetes
如果团队直接使用 Docker Hub 等公共 Registry,需要考虑镜像可见性、网络访问、权限管理以及企业内部代码和基础镜像的存储问题。
私有 Registry 的主要价值就是建立企业内部的镜像分发中心:
┌──────────────┐
│ CI/CD │
└──────┬───────┘
│ push
▼
┌──────────┐ ┌──────────────┐
│ Developer│───────▶│ Private │
│ Docker │ push │ Registry │
└──────────┘ └──────┬───────┘
│ pull
┌────────────┼────────────┐
▼ ▼ ▼
测试环境 生产环境 K8s 集群
Docker Registry 是镜像仓库的基础能力,而 Harbor 在 Registry 之上增加了 Web 管理、用户体系、项目权限、镜像扫描、Robot Account、复制等企业级能力。
因此,可以把两者理解为:
| 方案 | 定位 | 适合场景 |
|---|---|---|
| Docker Registry | 基础镜像仓库 | 简单、轻量的私有 Registry |
| Harbor | 企业级镜像仓库平台 | 团队、生产环境、CI/CD |
| Docker Hub | 公共云镜像仓库 | 公共镜像、开放项目 |
| 云厂商 Registry | 托管镜像仓库 | 云环境、无需自行维护 |
Docker Registry 是什么
Docker Registry 本质上是一个用于存储和分发容器镜像的服务。
例如:
docker.io/library/nginx:latest
其中:
docker.io
表示 Registry。
library/nginx
表示镜像仓库。
latest
表示 Tag。
使用私有 Registry 后,可以变成:
registry.example.com/library/nginx:latest
或者:
registry.example.com/backend/api:v1.0.0
Docker 客户端根据镜像地址中的 Registry 地址决定将镜像 Push 到哪里或者从哪里 Pull。
例如:
docker pull registry.example.com/backend/api:v1.0.0
以及:
docker push registry.example.com/backend/api:v1.0.0
Docker 官方也将 Registry 定义为用于存储和分发 Docker 镜像的服务。
使用 Docker Registry 搭建私有仓库
如果只是需要一个简单的私有镜像仓库,可以直接使用 Docker 官方 Registry 镜像。
创建目录:
mkdir -p /opt/registry/data
启动 Registry:
docker run -d \
--name registry \
--restart always \
-p 5000:5000 \
-v /opt/registry/data:/var/lib/registry \
registry:3
查看容器:
docker ps
应该可以看到:
registry
此时 Registry 运行在:
127.0.0.1:5000
测试 Registry:
curl http://127.0.0.1:5000/v2/
正常情况下会返回:
{}
给镜像添加 Registry Tag
假设本地已经存在:
my-api:1.0.0
添加私有 Registry Tag:
docker tag my-api:1.0.0 \
registry.example.com/my-api:1.0.0
然后 Push:
docker push registry.example.com/my-api:1.0.0
服务器上的 Registry 就会保存这个镜像。
其他服务器可以:
docker pull registry.example.com/my-api:1.0.0
Registry 的局限
Docker Registry 很轻量,但它解决的主要问题是:
镜像存储
镜像上传
镜像下载
如果企业需要:
用户管理
项目管理
RBAC
Web UI
镜像扫描
审计
Robot Account
镜像复制
镜像保留策略
垃圾回收
就需要在 Registry 基础上使用更完整的平台。
这也是 Harbor 的主要价值。
Harbor 是什么
Harbor 是一个开源的企业级 OCI 镜像仓库平台。
可以把 Harbor 理解成:
Harbor
┌────────────────────────────────────────┐
│ │
│ Web UI │
│ 用户 / 项目 / RBAC │
│ Robot Account │
│ 镜像扫描 │
│ 镜像复制 │
│ 审计日志 │
│ 垃圾回收 │
│ 镜像保留策略 │
│ │
├────────────────────────────────────────┤
│ Registry │
├────────────────────────────────────────┤
│ Storage │
└────────────────────────────────────────┘
Harbor 当前官方文档为 2.15 系列,并提供 Docker Compose 和 Kubernetes 两种主要部署方式。
对于普通企业内部环境,可以直接部署在一台 Docker 主机上。
Harbor 安装准备
Harbor 对服务器资源有一定要求。
官方文档给出的最低资源要求为:
| 资源 | 最低 | 推荐 |
|---|---|---|
| CPU | 2 Core | 4 Core |
| 内存 | 4 GB | 8 GB |
| 磁盘 | 40 GB | 160 GB |
Docker Compose 部署需要 Docker Engine 和 Docker Compose。
生产环境建议至少:
4 Core
8 GB RAM
160 GB+ SSD
如果镜像数量较多,磁盘空间应该根据实际镜像容量单独规划。
例如:
/opt/harbor/
├── harbor.yml
├── install.sh
└── data/
└── registry/
实际生产环境最好将镜像存储放到独立磁盘或者外部对象存储,而不是和系统盘混用。
配置 Harbor
首先下载对应版本的 Harbor 安装包,并解压。
进入 Harbor 目录:
cd /opt/harbor
复制配置文件:
cp harbor.yml.tmpl harbor.yml
修改:
hostname: registry.example.com
生产环境建议直接使用域名:
registry.example.com
而不是:
192.168.1.100
因为后续 HTTPS、证书以及 CI/CD 配置都会围绕 Registry 域名展开。
配置 HTTPS
生产环境不要使用 HTTP。
Harbor 官方明确建议生产环境使用 HTTPS;HTTP 更适合隔离网络中的测试或开发环境。
例如:
hostname: registry.example.com
https:
port: 443
certificate: /data/cert/registry.example.com.crt
private_key: /data/cert/registry.example.com.key
如果使用 Let’s Encrypt、DigiCert 等可信 CA 签发的证书,可以直接配置对应证书和私钥。Harbor 官方也推荐生产环境使用可信第三方 CA 证书。
安装并启动 Harbor
配置完成后执行:
./prepare
然后安装:
sudo ./install.sh
如果希望同时启用 Trivy,可以:
sudo ./install.sh --with-trivy
Harbor 安装程序会根据 harbor.yml 生成对应的 Docker Compose 配置并启动 Harbor 服务。
查看服务:
docker compose ps
如果部署正常,会看到多个 Harbor 相关服务。
例如:
proxy
core
portal
registry
registryctl
jobservice
database
redis
不同版本的服务组成可能存在差异,不应该依赖固定的容器名称。
访问:
https://registry.example.com
即可进入 Harbor Web 管理界面。
Harbor 项目与镜像仓库
Harbor 的一个重要概念是 Project。
例如创建:
backend
然后镜像可以按照项目进行组织:
registry.example.com/backend/api:v1.0.0
registry.example.com/backend/admin:v1.0.0
registry.example.com/backend/worker:v1.0.0
也可以按照业务划分:
registry.example.com/openuser/api:v1.0.0
registry.example.com/openknowledge/api:v1.0.0
registry.example.com/wenyan/api:v1.0.0
Harbor 中的 Project 同时也是权限控制的基本边界。Project 可以设置为 Public 或 Private,并对项目成员实施 RBAC。
例如:
backend
├── api
├── worker
└── scheduler
frontend
├── web
└── admin
infra
├── nginx
├── php
└── redis
这种组织方式比所有镜像直接堆在一个 Registry 中更加清晰。
Docker 登录、Push 与 Pull
创建 Project 后,就可以通过 Docker CLI 操作 Harbor。
登录 Harbor
docker login registry.example.com
输入 Harbor 用户名和密码。
登录成功后:
Login Succeeded
给镜像打 Tag
假设本地镜像:
my-api:1.0.0
执行:
docker tag my-api:1.0.0 \
registry.example.com/backend/my-api:1.0.0
查看:
docker images
可以看到:
my-api
registry.example.com/backend/my-api
Push
docker push registry.example.com/backend/my-api:1.0.0
Push 完成后,可以直接在 Harbor Web UI 中查看。
Pull
其他服务器执行:
docker login registry.example.com
然后:
docker pull registry.example.com/backend/my-api:1.0.0
完整流程就是:
Dockerfile
│
▼
docker build
│
▼
my-api:1.0.0
│
│ docker tag
▼
registry.example.com/backend/my-api:1.0.0
│
│ docker push
▼
Harbor
│
│ docker pull
▼
服务器 / Kubernetes
Harbor Robot Account
生产环境中的 CI/CD 不应该使用管理员账号执行:
docker login
更合理的方式是使用 Robot Account。
Robot Account 是 Harbor 提供给自动化任务使用的非人工账号,可以限制权限范围和有效期。项目级 Robot Account 只允许访问指定 Project,非常适合 CI/CD。
例如:
Project: backend
Robot Account:
robot-backend-ci
Permissions:
Pull Repository
Push Repository
CI/CD 中使用:
docker login registry.example.com \
-u 'robot$backend+ci' \
-p "$HARBOR_TOKEN"
然后:
docker push registry.example.com/backend/api:v1.0.0
这样即使 CI/CD 凭证泄露,也不会直接获得 Harbor 管理员权限。
对于跨多个 Project 的自动化任务,也可以使用 System Robot Account,并按项目配置权限。
Harbor 在 CI/CD 中的应用
将 Harbor 接入 CI/CD 后,典型流程如下:
Git Push
│
▼
CI Pipeline
│
├── Checkout
│
├── Test
│
├── Docker Build
│
├── Docker Tag
│
└── Docker Push
│
▼
Harbor
│
▼
Deploy
例如:
docker build \
-t registry.example.com/backend/api:${CI_COMMIT_SHA} \
.
docker push \
registry.example.com/backend/api:${CI_COMMIT_SHA}
如果同时维护版本 Tag:
docker tag \
registry.example.com/backend/api:${CI_COMMIT_SHA} \
registry.example.com/backend/api:v1.2.0
docker push \
registry.example.com/backend/api:v1.2.0
生产环境建议优先使用不可变版本标识,例如:
v1.2.0
或者:
a8f52d7
而不是完全依赖:
latest
例如:
registry.example.com/backend/api:v1.2.0
registry.example.com/backend/api:a8f52d7
这样部署系统可以准确知道运行的是哪个镜像版本。
Harbor 的生产环境配置建议
私有 Registry 真正进入生产环境后,重点已经不只是“能不能 Push”,而是镜像仓库本身的可靠性和安全性。
HTTPS
生产环境:
Docker Client
│
│ HTTPS
▼
Harbor
不要长期使用:
HTTP
Harbor 官方明确建议生产环境使用 HTTPS。
权限隔离
不要所有开发人员都使用:
admin
应该按照 Project 分配权限:
backend
├── Developer
├── Maintainer
└── CI Robot
frontend
├── Developer
└── CI Robot
CI 使用 Robot Account
不要把个人账号密码直接写进 CI:
HARBOR_USERNAME: admin
HARBOR_PASSWORD: xxx
应该使用:
Robot Account
│
├── Push
└── Pull
并配置有效期和最小权限。
镜像 Tag 规范
建议统一:
项目/服务:版本
例如:
registry.example.com/backend/api:v1.2.0
registry.example.com/backend/worker:v1.2.0
CI 构建也可以增加 Git Commit:
registry.example.com/backend/api:a8f52d7
镜像清理
长期运行的 CI/CD 会产生大量镜像:
api:a001
api:a002
api:a003
...
api:a999
如果没有清理策略,Registry 存储空间会持续增长。
因此生产环境需要结合:
Tag 保留策略
镜像删除
Registry Garbage Collection
磁盘监控
进行管理。
Docker Registry 与 Harbor 如何选择
两者并不是完全竞争关系。
可以按照实际需求选择:
| 场景 | 推荐 |
|---|---|
| 本地测试 | Docker Registry |
| 单机简单私有仓库 | Docker Registry |
| 小型项目 | Docker Registry |
| 团队开发 | Harbor |
| 企业内部镜像仓库 | Harbor |
| CI/CD | Harbor |
| 需要 RBAC | Harbor |
| 需要 Web UI | Harbor |
| 需要镜像扫描 | Harbor |
| 需要 Robot Account | Harbor |
| 多项目、多团队 | Harbor |
| Kubernetes 企业环境 | Harbor |
简单来说:
只需要 Registry
│
▼
Docker Registry
需要完整镜像管理平台
│
▼
Harbor
对于个人开发、小型项目,直接使用 Registry 可以减少系统复杂度。
如果已经存在多个项目、CI/CD、生产服务器以及 Kubernetes 集群,Harbor 通常更加合适。
一个完整的生产发布流程
最终可以把前面的 Docker 内容串成一条完整链路:
Git
│
git push
│
▼
CI/CD
│
docker build
│
▼
Docker Image
│
docker tag
│
▼
registry.example.com
│
docker push
│
▼
Harbor
│
┌────────┴────────┐
│ │
▼ ▼
测试环境 生产环境
│ │
docker pull docker pull
│ │
▼ ▼
Container Container
例如:
# 1. 构建
docker build \
-t registry.example.com/backend/api:v1.2.0 \
.
# 2. 登录 Harbor
docker login registry.example.com
# 3. 推送
docker push \
registry.example.com/backend/api:v1.2.0
部署服务器:
docker login registry.example.com
docker pull \
registry.example.com/backend/api:v1.2.0
docker run -d \
--name api \
registry.example.com/backend/api:v1.2.0
这样,Docker 镜像就从开发环境进入了一个完整的:
Build
↓
Tag
↓
Push
↓
Harbor
↓
Pull
↓
Deploy
发布体系。
总结
Docker Registry 解决的是 Docker 镜像的集中存储与分发问题,而 Harbor 则在 Registry 基础上进一步提供了项目管理、RBAC、Web UI、Robot Account、镜像扫描、复制和运维管理等企业级能力。
对于个人项目:
Docker Registry
通常已经足够。
对于团队和生产环境:
Harbor
更加合适。
实际生产环境建议采用:
Docker Build
↓
Tag
↓
Harbor HTTPS
↓
Project
↓
Robot Account
↓
CI/CD Push
↓
服务器 / Kubernetes Pull
并重点做好:
HTTPS
权限隔离
Robot Account
镜像 Tag 规范
镜像保留策略
磁盘监控
备份
这样,Harbor 才不仅是一个“存镜像的服务器”,而是整个 Docker 镜像交付体系的核心基础设施。
参考资料