搭建Harbor企业级Docker仓库

Harbor简介

Harbor介绍

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源Docker Distribution。作为一个企业级私有Registry服务器,Harbor提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有Registry中,确保数据和知识产权在公司内部网络中管控。另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。

Harbor特性

  • 基于角色的访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限
  • 镜像复制:镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景
  • 图形化用户界面:用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间
  • AD/LDAP 支持:Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理
  • 审计管理:所有针对镜像仓库的操作都可以被记录追溯,用于审计管理
  • 国际化:已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来
  • RESTful API:RESTful API 提供给管理员对于Harbor更多的操控,使得与其它管理软件集成变得更容易
  • 部署简单:提供在线和离线两种安装工具,也可以安装到vSphere平台(OVA方式)虚拟设备

Harbor组件

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的核心功能,主要提供以下服务:
    • UI:提供图形化界面,帮助用户管理registry上的镜像(image),并对用户进行授权。
    • webhook:为了及时获取registry 上image状态变化的情况,在Registry上配置webhook,把状态变化传递给UI模块。
    • token 服务:负责根据用户权限给每个docker push/pull命令签发token. Docker 客户端向Regiøstry服务发起的请求,如果不包含token,会被重定向到这里,获得token后再重新向Registry进行请求。
  • Database:为core services提供数据库服务,负责储存用户权限、审计日志、Docker image分组信息等数据。
  • Job Services:提供镜像远程复制功能,可以把本地镜像同步到其他Harbor实例中。
  • Log collector:为了帮助监控Harbor运行,负责收集其他组件的log,供日后进行分析。

Harbor实现

Harbor的每个组件都是以Docker容器的形式构建的,官方也是使用Docker Compose来对它进行部署。用于部署Harbor的Docker Compose模板位于harbor/docker-compose.yml,打开这个模板文件,发现Harbor是由7个容器组成的;

1
2
3
4
5
6
7
8
9
10
# docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------------------------------------
harbor-adminserver /harbor/harbor_adminserver Up
harbor-db docker-entrypoint.sh mysqld Up 3306/tcp
harbor-jobservice /harbor/harbor_jobservice Up
harbor-log /bin/sh -c crond && rm -f ... Up 127.0.0.1:1514->514/tcp
harbor-ui /harbor/harbor_ui Up
nginx nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:80->80/tcp
registry /entrypoint.sh serve /etc/ ... Up 5000/tcp
  • nginx:nginx负责流量转发和安全验证,对外提供的流量都是从nginx中转,所以开放https的443端口,它将流量分发到后端的ui和正在docker镜像存储的docker registry
  • harbor-jobservice:harbor-jobservice 是harbor的job管理模块,job在harbor里面主要是为了镜像仓库之前同步使用的
  • harbor-ui:harbor-ui是web管理页面,主要是前端的页面和后端CURD的接口
  • registry:registry就是docker原生的仓库,负责保存镜像
  • harbor-adminserver:harbor-adminserver是harbor系统管理接口,可以修改系统配置以及获取系统信息
  • harbor-db:harbor-db是harbor的数据库,这里保存了系统的job以及项目、人员权限管理。由于本harbor的认证也是通过数据,在生产环节大多对接到企业的ldap中
  • harbor-log:harbor-log是harbor的日志服务,统一管理harbor的日志。通过inspect可以看出容器统一将日志输出的syslog

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

安装部署

1、安装最新版的docker、docker-compose

1
2
3
curl -fsSL https://get.docker.com/ | sh  或  yum install docker-ce-18.03.1.ce
curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose

验证

1
2
docker version
docker-compose --version

2、安装harbor

登录下载相应版本的harbor: https://github.com/goharbor/harbor/releases

1
2
wget https://github.com/goharbor/harbor/releases/download/v1.8.1/harbor-offline-installer-v1.8.1.tgz
tar zxf harbor-offline-installer-v1.8.1.tgz

编辑harbor.yml然后执行./install.sh

安装完成后在浏览器使用 172.16.119.225即可登陆,如果用域名的话,可以配置nginx如下:

1
2
3
4
5
6
7
server {
listen 80;
server_name harbor.xxx.com;
location / {
proxy_pass http://172.16.119.225:80;
}
}

即可使用域名登陆,登陆账号密码在harbor.yml配置的,默认账号密码:admin / Harbor12345登录后可修改密码。

Harbor控制台

Harbor的启动和停止

1
2
3
4
5
6
# 启动Harbor
docker-compose start
# 停止Harbor
docker-comose stop
# 重启Harbor
docker-compose restart

测试上传下载镜像

1、所有服务器修改docker客户端配置

vim /usr/lib/systemd/system/docker.service增加--insecure-registry=http://172.16.119.225:80即可。

1
ExecStart=/usr/bin/dockerd  --insecure-registry=http://172.16.119.225:80  #harbor.yml里配置的hostname值

重启Docker

1
systemctl restart docker

或创建/etc/docker/daemon.json文件,在文件中指定仓库地址,然后重新Docker

1
2
3
{
"insecure-registries":["172.16.119.225:80"]
}

2、创建Dockerfile

1
2
3
4
5
6
from docker.io/tomcat:latest
MAINTAINER yezhou
RUN rm -rf /usr/local/openjdk-8
RUN rm -rf /usr/local/tomcat
COPY jdk1.8.0_92 /usr/local/jdk1.8.0_92
COPY tomcat /usr/local/tomcat

3、创建镜像

tag名称里172.16.119.225:80/library/是不变的,172.16.119.225:80表示私库地址,library是仓库项目名,可以更改,但私库里要先创建好

1
docker build -t 172.16.119.225:80/library/tomcat:wuyun .

4、登录私库然后把镜像推送到Harbor仓库

1
2
docker login 172.16.119.225:80
docker push 172.16.119.225:80/library/tomcat:wuyun

如果不是自己创建的镜像,需要先执行docker tags给镜像做tag再推送,如:

1
2
3
docker pull flannel
docker tag quay.io/coreos/flannel:v0.11.0-amd64 172.16.119.225:80/library/flannel:v0.11.0-amd64
docker push 172.16.119.225:80/library/flannel:v0.11.0-amd64

删除这种同id不同tag的镜像

1
docker rmi 172.16.119.225:80/library/flannel:v0.11.0-amd64

5、登陆web页面查看镜像

Harbor控制台查看镜像

6、在别的服务器上拉取镜像,服务器上要先更改好私库地址

1
docker pull 172.16.119.225:80/library/tomcat:wuyun   

Harbor配置TLS证书

参考文章:https://goharbor.io/docs/2.2.0/install-config/configure-https/

因为我们上面对Harbor的配置都是使用的http协议访问,但是我们工作中一般都是配置https访问。所以我给大家演示一下怎么配置Harbor可以使用https访问,以及配置TLS证书都需要做哪些工作。

因为Harbor默认使用http协议访问,所以我们这里在配置文件中,开启https配置;

1、编辑harbor.yml

1
2
3
4
5
6
7
8
9
hostname: 172.16.119.225

#http:
# port: 80

https:
port: 443
certificate: /etc/certs/172.16.119.225.crt
private_key: /etc/certs/172.16.119.225.key

2、创建目录并生成ca文件

1
2
mkdir /etc/certs && cd /etc/certs/
openssl genrsa -out /etc/certs/ca.key 2048

3、创建自签名证书key文件,注意CN的值,更改和harbor.yml里hostname值一样即可

1
openssl req -x509 -new -nodes -key /etc/certs/ca.key -subj "/CN=172.16.119.225" -days 5000 -out /etc/certs/ca.crt

4、生成服务器端私钥和CSR签名请求

1
2
openssl genrsa -out 172.16.119.225.key 4096   #172.16.119.225是ip或者主机名
openssl req -sha512 -new -subj "/CN=172.16.119.225" -key 172.16.119.225.key -out 172.16.119.225.csr

5、签发服务器证书

创建文件v3.ext并生成crt文件

1
2
3
4
5
6
7
8
9
10
11
12
13
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=172.16.119.225
DNS.2=test-04
IP.1=172.16.119.225 #其他需要连接docker私库的服务器IP地址
IP.2=172.16.119.224
IP.3=172.16.119.223
IP.4=172.16.119.***
1
openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in 172.16.119.225.csr -out 172.16.119.225.crt

6、配置docker证书

为所有需要用https的 Docker服务器配置服务器证书,密钥和CA

Docker守护程序将.crt文件解释为CA证书,将.cert文件解释为客户端证书。

将crt文件转换为cert文件

1
openssl x509 -inform PEM -in 172.16.119.225.crt -out 172.16.119.225.cert

将文件cert key和ca文件拷贝到/etc/docker/certs.d/172.16.119.225如果没有目录就新建,目录格式不能错。

1
2
3
4
5
6
# 如果如下目录不存在,请创建,如果有域名请按此格式依次创建
# mkdir -p /etc/docker/certs.d/192.168.50.85
# mkdir -p /etc/docker/certs.d/[IP2]
# mkdir -p /etc/docker/certs.d/[example1.com]
# 如果端口为443,则不需要指定。如果为自定义端口,请指定端口
# /etc/docker/certs.d/yourdomain.com:port
1
2
3
4
5
6
7
mkdir -p /etc/docker/certs.d/172.16.119.225

cp 172.16.119.225.cert /etc/docker/certs.d/172.16.119.225

cp 172.16.119.225.key /etc/docker/certs.d/172.16.119.225

cp ca.crt /etc/docker/certs.d/172.16.119.225

7、重启Docker然后为Harbor生成配置文件

1
2
systemctl restart docker
./prepare

如果Harbor已在运行,请停止并删除现有实例。然后重启实例

1
2
3
docker-compose down -v
docker-compose up -d
docker-compose ps

如果nginx无法启动且查看容器日志也查看不了,报如下错误

1
Error response from daemon: configured logging driver does not support reading

遇到此问题可以关注docker-compose.yml以下选项是否对应

1
2
3
4
source: /data/cert/server.key
target: /etc/cert/server.key
source: /data/cert/server.crt
target: /etc/cert/server.crt

我这查看显示source 都是ca.crt,因为我复制错了,docker-compose.yml是在./install后映射的harbor.yml内容,所以更改harbor.yml后重新安装即可

1
2
3
4
5
6
# cat docker-compose.yml | grep cert
- ./common/config/core/certificates/:/etc/core/certificates/:z
source: /etc/certs/ca.crt
target: /etc/cert/server.key
source: /etc/certs/ca.crt
target: /etc/cert/server.crt

8、测试

所有Docker服务器先更改/etc/docker/daemon.json再重启Docker

1
2
3
{
"insecure-registries":["172.16.119.225:443"]
}

然后docker login 172.16.119.225:443如果提示x509: certificate signed by unknown authority错误,则需要添加主机信任,CentOS操作如下:

1
2
3
cp 172.16.119.225.crt /etc/pki/ca-trust/source/anchors/172.16.119.225.crt

update-ca-trust

再次登录即可,如果端口不是443端口,登录需要指明端口,如:docker login 172.16.119.225:9999

注:删除~/.docker/config.json文件内 auths内容可以删除登录记录