为什么需要私有 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 对服务器资源有一定要求。

官方文档给出的最低资源要求为:

资源最低推荐
CPU2 Core4 Core
内存4 GB8 GB
磁盘40 GB160 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/CDHarbor
需要 RBACHarbor
需要 Web UIHarbor
需要镜像扫描Harbor
需要 Robot AccountHarbor
多项目、多团队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 镜像交付体系的核心基础设施。

参考资料