简介

Harbor是VMware公司最近开源的企业级Docker Registry项目, 项目地址为https://github.com/vmware/harbor 其目标是帮助用户迅速搭建一个企业级的Docker registry服务。它以Docker公司开源的registry为基础,提供了管理UI, 基于角色的访问控制(Role Based Access Control),AD/LDAP集成、以及审计日志(Audit logging) 等企业用户需求的功能,同时还原生支持中文。Harbor的每个组件都是以Docker容器的形式构建的,使用Docker Compose来对它进行部署。用于部署Harbor的Docker Compose模板位于 /Deployer/docker-compose.yml,由5个容器组成:

Proxy: 由Nginx 服务器构成的反向代理。

Registry:由Docker官方的开源registry 镜像构成的容器实例。

UI: 即架构中的core services, 构成此容器的代码是Harbor项目的主体。

Mysql: 由官方MySql镜像构成的数据库容器。

Log: 运行着rsyslogd的容器,通过log-driver的形式收集其他容器的日志。

这几个容器通过Docker link的形式连接在一起,在容器之间通过容器名字互相访问。对终端用户而言,只需要暴露proxy (即Nginx)的服务端口。

快速部署方法

Harbor使用Docker-compose部署,后续所有的配置以及部署均在$HARBOR_HOME/Deploy/`目录下完成,因此若无特别说明,工作目录都在该目录下。

首先需要进行简单的配置,配置文件为harbor.cfg,配置项如下:

hostname:hostname为外部可访问的地址,即bind addr,通常设置为本地公有IP,若内部使用DNS,可设置为主机名。

auth_mode:Harbor支持两种认证方式,默认为本地存储,即账号信息存储在mysql下,本文先使用本地存储方式,另外一种认证方式LDAP将在后续章节单独介绍。

设置完毕后,配置文件为:

hostname = 42.62.x.x

ui_url_protocol = http

##The password of Harbor admin, change this before any production use. harbor_admin_password= admin

##By default the auth mode is db_auth, i.e. the credentials are stored in a local database. #Set it to ldap_auth if you want to verify a user’s credentials against an LDAP server. auth_mode = ldap_auth

#The password for the root user of mysql db, change this before any production use. db_password = root123

#Switch for self-registration feature

self_registration = on

运行./prepare脚本更新配置。完成配置后,就可以使用docker-compose快速部署harbor:

docker-compose up -d

安装完成后,访问Web UI,地址:http://bind_addr,即配置的hostname地址,端口为80。如图:

使用harbor
使用harbor
Web UI

安装完成后,打开Web UI,点击登录,默认账户admin/Harbor12345,登录成功后进入项目管理界面:

管理界面用户可以点击“我的项目”进行项目管理,比如新建项目、用户以及权限管理等。点击项目名称,进入该项目下的镜像管理界面,可以查看、检索镜像

docker client

以上是UI界面的使用,接下来介绍如何使用docker client进行镜像的管理,由于harbor只支持Registry V2 API,因此Docker client版本必须>= 1.6.0。

由于我们配置认证服务使用的是http,Docker认为是不安全的,要使用我们部署的镜像仓库,需要配置本地docker,修改配置文件(/etc/default/docker)为:

DOCKER_OPTS=”$DOCKER_OPTS –insecure-registry 42.62.x.x”

其中42.62.x.x是我们部署Harbor的地址,即hostname配置项值。配置完后需要重启docker服务。

验证能否登录:

docker login 42.62.x.x

# docker login -u admin -p Harbor12345 -e test@gmail.com 42.62.x.x

登录成功后显示如下:

登录成功接下来我们上传一个镜像,以ubuntu镜像为例,首先从docker hub拉取ubuntu镜像:

docker pull ubuntu:14.04

然后为该镜像打上新的标签,标签格式为:Harbor地址/项目名/镜像名称:镜像标签,如

42.62.x.x/library/ubuntu:14.04:

docker tag ubuntu:14.04 42.62.x.x/library/ubuntu:14.04

push我们的镜像到harbor仓库中:

docker push ubuntu:14.04 42.62.x.x/library/ubuntu:14.04

push镜像

push成功后,我们就可以从harbor仓库中使用docker pull拉取我们的镜像了,注意如果是私有项目,必须先使用docker login登录:

docker pull 42.62.x.x/library/ubuntu:14.04

使用harbor作为mirror registry
Mirror Registry简介

Mirror是Docker Registry的一种特殊类型,它起到了类似代理服务器的缓存角色,在用户和Docker Hub之间做Image的缓存。 官方定义为:

Such a registry is provided by a third-party hosting infrastructure but is targeted at their customers only. Some mechanism ensures that public images are pulled from a sponsor registry to the mirror registry, to make sure that the customers of the third-party provider can docker pull those images locally.

其基本工作原理是,当用户pull一个镜像时,若镜像在mirror 服务器存在,则直接从mirror服务器拉取,否则若不存在该镜像,则由mirror server自动代理往dockerhub(可配置)中拉取镜像,并缓存到mirror服务器中,当客户再次拉取这个镜像时,直接从mirror server中拉取,不需要再次从dockerhub中拉取。

注意Mirror跟Private Registry有本质区别,参考DaoCloud宣布Docker Hub Mirror服务永久免费 :

Private Registry是开发者或者企业自建的Image存储库,通常用来保存企业内部的Docker Image,用于内部开发流程和产品的发布、版本控制。Mirror是一种代理中转服务,我们提供的Mirror服务,直接对接Docker Hub的官方Registry,Docker Hub上有数以十万计的各类Docker Image。在使用Private Registry时,需要在Docker Pull,或Dockerfile中直接键入Private Registry的地址,通常这样会导致跟Private Registry的绑定,缺少灵活性。



原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


我们在运行./prepare之前修改config/registry/config.yml文件,追加以下配置:

proxy:

remoteurl: https://registry-1.docker.io

如果需要访问私有仓库,需要填写dockerhub的用户名和密码:

proxy:

remoteurl: https://registry-1.docker.io

username: [username]

password: [password]

然后重新启动harbor服务:

# 注意不要执行./prepare,否则会覆盖修改的配置

docker-compose stop

docker-compose rm -f

docker-compose up -d

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


除了设置harbor(或者registry),还需要配置本地docker服务,指定–registry-mirror参数,修改docker配置文件(/etc/default/docker):

DOCKER_OPTS=”$DOCKER_OPTS –registry-mirror=http://42.62.x.x –insecure-registry 42.62.x.x”

注意替换42.62.x.x为你的registry地址。

注意:修改了docker配置文件,必须重启docker服务才能生效。

harbor由于引进了认证功能,因此push操作时,必须保证project存在,比如push krystism/ffmpeg,必须保证harbor创建了krystism project,否则会失败。为了能够正常push/pull dockerhub的官方镜像,务必创建library project,如图:

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


2.架构介绍

1)    主要组件

Harbor在架构上主要由6个组件构成:

·      Proxy:Harbor的registry, UI, token等服务,通过一个前置的反向代理统一接收浏览器、Docker客户端的请求,并将请求转发给后端不同的服务。

·      Registry: 负责储存Docker镜像,并处理docker push/pull 命令。由于我们要对用户进行访问控制,即不同用户对Docker image有不同的读写权限,Registry会指向一个token服务,强制用户的每次docker pull/push请求都要携带一个合法的token, Registry会通过公钥对token 进行解密验证。

·      Core services: 这是Harbor的核心功能,主要提供以下服务:

o   UI:提供图形化界面,帮助用户管理registry上的镜像(image), 并对用户进行授权。

o   webhook:为了及时获取registry 上image状态变化的情况, 在Registry上配置webhook,把状态变化传递给UI模块。

o   token 服务:负责根据用户权限给每个docker push/pull命令签发token. Docker 客户端向Regiøstry服务发起的请求,如果不包含token,会被重定向到这里,获得token后再重新向Registry进行请求。

·      Database:为core services提供数据库服务,负责储存用户权限、审计日志、Docker image分组信息等数据。

       Job Services:提供镜像远程复制功能,可以把本地镜像同步到其他Harbor实例中。

·      Log collector:为了帮助监控Harbor运行,负责收集其他组件的log,供日后进行分析。

各个组件之间的关系如下图所示:


原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


2)    实现

Harbor的每个组件都是以Docker 容器的形式构建的,因此很自然地,我们使用Docker Compose来对它进行部署。

在源代码中(https://github.com/vmware/harbor), 用于部署Harbor的Docker Compose 模板位于 /Deployer/docker-compose.yml. 打开这个模板文件,会发现Harbor由5个容器组成:

·      proxy: 由Nginx 服务器构成的反向代理。

·      registry:由Docker官方的开源registry 镜像构成的容器实例。

·      ui: 即架构中的core services, 构成此容器的代码是Harbor项目的主体。

·      mysql: 由官方MySql镜像构成的数据库容器。

       job services: 通过状态机机制实现远程镜像复制功能,包括镜像删除也可以同步到远端Harbor实例。

·      log: 运行着rsyslogd的容器,通过log-driver的形式收集其他容器的日志。

这几个容器通过Docker link的形式连接在一起,这样,在容器之间可以通过容器名字互相访问。对终端用户而言,只需要暴露proxy (即Nginx)的服务端口。

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


  1.  docker login

假设我们将Harbor部署在IP 为192.168.1.10的虚机上。用户通过docker login命令向这个Harbor服务发起登录请求:

# docker login 192.168.1.10

当用户输入所需信息并点击回车后,Docker 客户端会向地址 “192.168.1.10/v2/” 发出HTTP GET请求。 Harbor的各个容器会通过以下步骤处理:

(a) 首先,这个请求会由监听80端口的proxy容器接收到。根据预先设置的匹配规则, 容器中的Nginx会将请求转发给后端的registry 容器;

(b) 在registry容器一方,由于配置了基于token的认证,registry会返回错误代码401,提示Docker客户端访问token服务绑定的URL。在Harbor中,这个URL指向Core Services;

(c) Docker  客户端在接到这个错误代码后,会向token服务的URL发出请求,并根据HTTP协议的Basic Authentication规范,将用户名密码组合并编码,放在请求头部(header);

(d)类似地,这个请求通过80端口发到proxy容器后,Nginx会根据规则把请求转发给ui容器,ui容器监听token服务网址的处理程序接收到请求后,会将请求头解码,得到用户名、密码;

(e) 在得到用户名、密码后,ui容器中的代码会查询数据库,将用户名、密码与mysql容器中的数据进行比对(注:ui 容器还支持LDAP的认证方式,在那种情况下ui会试图和外部LDAP服务进行通信并校验用户名/密码)。比对成功,ui容器会返回表示成功的状态码, 并用密钥生成token,放在响应体中返回给Docker 客户端。

这个过程中组件间的交互过程如下图所示:

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


 

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.

  至此,一次docker login 成功地完成了,Docker客户端会把步骤(c)中编码后的用户名密码保存在本地的隐藏文件中。

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


 

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


至此,一次docker login 成功地完成了,Docker客户端会把步骤 (c) 中编码后的用户名密码保存在本地的隐藏文件中。

原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.


2.   docker push

用户登录成功后用docker push命令向Harbor 推送一个Docker image:

# docker push 192.168.1.10/library/hello-world

(a) 首先,docker 客户端会重复login的过程,首先发送请求到registry,之后得到token 服务的地址;

(b) 之后,Docker 客户端在访问ui容器上的token服务时会提供额外信息,指明它要申请一个对image library/hello-world进行push操作的token;

(c) token 服务在经过Nginx转发得到这个请求后,会访问数据库核实当前用户是否有权限对该image进行push。如果有权限,它会把image的信息以及push动作进行编码,并用私钥签名,生成token返回给Docker客户端;

(d) 得到token之后 Docker客户端会把token放在请求头部,向registry发出请求,试图开始推送image。 Registry 收到请求后会用公钥解码token并进行核对,一切成功后,image的传输就开始了。

 我们省去proxy转发的步骤,下图描述了这个过程中各组件的通信过程:

4.参考材料



原理如图:mirror原理图Harbor目前不支持pull cache功能,已提交issue #120。不过我们只需要手动修改下配置即可完成,具体配置可参考官方Registry as a pull through cache.

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐