现在已经是容器化时代,加上 Kubernetes 的助力,基本上应用都是跑在容器里。

企业使用容器,大部分是需要自己的镜像仓库服务器的,Docker官方发布了镜像仓库容器 registry,普通使用问题不大,不过在权限、管理上不是特别方便。

基于此,VMware开源了企业级registry:Harbor,提供权限控制,更安全、性能更高,可以方便的管理镜像仓库,同时还有WEB管理界面,可谓是应有尽有。

本文将介绍如何搭建Harbor(版本1.10),Harbor的搭建并不复杂,但对于新手上路来说,还是挺多步骤的,想一次点亮也不是件容易事。

环境准备

  • 系统:CentOS 7.7
  • docker 19.03.7
  • docker-compose 1.18.0
  • Nginx 1.14.2,需要开启ssl模块,通过nginx -V查看有没有--with-http_ssl_module
  • 搭建域名:harbor.yourhost.com

硬件需求:

Resource Minimum Recommended
CPU 2 CPU 4 CPU
Mem 4 GB 8 GB
Disk 40 GB 160 GB

搭建方式

Harbor 自带 https 功能,我们想使用 https 默认端口 443 ,但又不希望机器端口被 Harbor 独占,所以我们不开启 Harbor 的 https 功能,使用 Nginx 进行代理。

所以整个搭建过程主要步骤为:

  1. 搭建 Harbor 服务
  2. 生成自签名 ssl 证书
  3. Nginx HTTPS 代理
  4. 客户端信任自签名证书,才能正常访问服务

搭建 Harbor 服务

下载安装包

首先我们需要下载 Harbor 的安装包,官方提供了两个选择:在线安装包、离线安装包。
它们的区别是离线包将需要的镜像都打包好了,安装的时候会自动加载镜像,基于某些不可描述的原因,我们选择离线包。

离线包可以在 这里 下载

现在,我们拥有了安装包harbor-offline-installer-v1.10.1.tgz,并打算将 Harbor 放置在/data/harbor

1
2
3
4
5
6
7
mkdir /data
cp harbor-offline-installer-v1.10.1.tgz /data
cd /data
# 解压离线包
tar zxvf harbor-offline-installer-v1.10.1.tgz
cd harbor
mkdir data log

现在我们的/data/harbor将会是:

1
2
3
4
5
6
7
8
9
10
# 用 data 来放置 harbor 产生的内容
#log 放置日志
-rw-r--r-- 1 root root 3398 Feb 10 14:18 common.sh
drwxr-xr-x 2 root root 4096 Mar 11 14:55 data
-rw-r--r-- 1 root root 677974489 Feb 10 14:19 harbor.v1.10.1.tar.gz
-rw-r--r-- 1 root root 5882 Feb 10 14:18 harbor.yml
-rwxr-xr-x 1 root root 2284 Feb 10 14:18 install.sh
-rw-r--r-- 1 root root 11347 Feb 10 14:18 LICENSE
drwxr-xr-x 2 root root 4096 Mar 11 14:55 log
-rwxr-xr-x 1 root root 1749 Feb 10 14:18 prepare

配置启动 Harbor

现在进入/data/harbor,编辑文件harbor.yml

  1. hostname改为:harbor.yourhost.com
  2. http.port改为:8000,这是 Harbor 监听的 http 端口
  3. 解开external_url注释,值改为:https://harbor.yourhost.com
  4. harbor_admin_password是默认管理员admin的密码,修改成你要的密码
  5. database是Harbor的数据库,看自己情况要不要修改
  6. data_volume改为:/data/harbor/data
  7. log.level修改为:error
  8. log.local.location改为:/data/harbor/log
  9. https的内容注释掉
  10. 其他的默认即可。像 redis 之类的要不要用外部服务,根据自己需要决定。

配置完成后,我们执行./install.sh进行安装。
假设一切顺利,我们便可以成功开启Harbor服务。我们可以通过docker-compose ps查看是否成功启动:

1
2
3
4
5
6
7
8
9
10
11
  Name                     Command                  State            Ports
--------------------------------------------------------------------------------------
harbor-core /harbor/harbor_core Up
harbor-db /docker-entrypoint.sh Up 5432/tcp
harbor-jobservice /harbor/harbor_jobservice ... Up
harbor-log /bin/sh -c /usr/local/bin/ ... Up 127.0.0.1:1514->10514/tcp
harbor-portal nginx -g daemon off; Up 8080/tcp
nginx nginx -g daemon off; Up 0.0.0.0:8000->8080/tcp
redis redis-server /etc/redis.conf Up 6379/tcp
registry /home/harbor/entrypoint.sh Up 5000/tcp
registryctl /home/harbor/start.sh Up

curl localhost:8000你应该能看到 Harbor 返回的页面信息,这个时候,Harbor 的 http 服务已经开启起来。

启动失败

基于不同的环境,install.sh 是有可能执行失败的,比如:

  • 机器没有安装docker-compose,centos 的话就通过yum install docker-compose安装一下。
  • Harbor 启动了许多它依赖的容器,比如:nginx、redis,并且默认 container 名称就是 nginx、redis,假如我们机器上原本已经启动了相关容器,那容器名是可能冲突的。这时候需要修改 install 脚本生成的docker-compose.yml文件,找到相关容器的container_name,修改成不会冲突的容器名。

配置HTTPS

接下来我们需要配置 Nginx 来代理 https。因为现在的 Docker 版本默认要求走 https。对于熟悉 Nginx 的童鞋来说配置不麻烦,出问题的大多可能还是自签名证书的环节。

生成自签名 ssl 证书

首先需要确保我们机器已经安装了openssl,然后执行下面的命令(将里面的域名更换成自己的域名,days相关的代表的是证书的有效期,我们可以改长一些):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
openssl genrsa -out harbor.yourhost.com.ca.key 4096
openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=harbor.yourhost.com" \
-key harbor.yourhost.com.ca.key \
-out harbor.yourhost.com.ca.crt

# 生成服务证书
openssl genrsa -out harbor.yourhost.com.key 4096

openssl req -sha512 -new \
-subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=harbor.yourhost.com" \
-key harbor.yourhost.com.key \
-out harbor.yourhost.com.csr

cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=harbor.yourhost.com
EOF

openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA harbor.yourhost.com.ca.crt -CAkey harbor.yourhost.com.ca.key -CAcreateserial \
-in harbor.yourhost.com.csr \
-out harbor.yourhost.com.crt

执行完上面的命令后,会生成5个证书:

  • harbor.yourhost.com.ca.key
  • harbor.yourhost.com.ca.crt
  • harbor.yourhost.com.key
  • harbor.yourhost.com.csr
  • harbor.yourhost.com.crt

证书到此生成完毕,后面需要给到 Nginx 和 Docker 客户端使用。

Nginx配置访问

现在我们配置 Nginx 代理 Harbor。创建配置文件harbor.yourhost.com.conf,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
server {
listen 80;
server_name harbor.yourhost.com;
return 308 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name harbor.yourhost.com;

# SSL 证书
ssl_certificate /data/harbor/certs/harbor.yourhost.com.crt;
# SSL 私钥
ssl_certificate_key /data/harbor/certs/harbor.yourhost.com.key;
client_max_body_size 0;
chunked_transfer_encoding on;

proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_http_version 1.1;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

location / {
proxy_redirect off;
proxy_ssl_verify off;
proxy_ssl_session_reuse on;

proxy_pass http://localhost:8000;
}
}

创建完成,nginx -t校验下,没问题后nginx -s reload重新读取配置。
现在,我们访问一下试试:

1
curl -k -H "Host:harbor.yourhost.com" https://localhost

假设你 Nginx 不是放在 Harbor 的机器上,配置时记得将ip改一下。
上面 curl 我们用了 -k 参数,因为我们的证书是自签名证书,目前我们还没配置机器和Docker对证书的信任。这一步在后面进行。

下面这一步至关重要,如果没有配置好,会导致push镜像一直不成功,多次重试后报出EOF错误

进入Harbor目录,修改文件common/config/nginx/nginx.conf,会看到文件中关于header(X-Forwarded-Proto)有注明:

1
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings

我们需要将有这句提示的proxy_set_header X-Forwarded-Proto $scheme;都删除或者注释掉。
然后重启 Harbor 服务。

1
2
docker-compose down
docker-compose up -d

客户端信任自签名证书

接下来我们需要配置对证书的信任。

为 Docker 配置自签名证书信任

通过上一步我们已经生成好了自签名证书,现在需要将它配置给docker客户端,需要连接仓库的机器客户端都要。
Docker 使用的是.cert证书文件,我们需要进行转换:

1
2
3
4
5
openssl x509 -inform PEM -in harbor.yourhost.com.crt -out harbor.yourhost.com.cert
mkdir -p /etc/docker/certs.d/harbor.yourhost.com/
cp harbor.yourhost.com.cert /etc/docker/certs.d/harbor.yourhost.com/
cp harbor.yourhost.com.key /etc/docker/certs.d/harbor.yourhost.com/
cp harbor.yourhost.com.ca.crt /etc/docker/certs.d/harbor.yourhost.com/

假设我们使用的不是默认的https端口(443),那放入的Docker文件夹名应该为/etc/docker/certs.d/harbor.yourhost.com:端口/

然后重启 Docker 引擎:systemctl restart docker

现在,我们可以使用Docker正常地使用Harbor仓库(当然还要把域名解析配置好):

1
2
3
# 默认管理员账号是admin,密码要对应回前面启动Harbor时配置里设置的。
docker login harbor.yourhost.com -u admin
# 输入密码

有时候我们可能需要多配置一个环节,机器对证书的信任。
将证书 harbor.vipc.me.ca.crt 复制到 /etc/pki/ca-trust/source/anchors/,然后执行 update-ca-trust。

可能出现的问题

  1. 发现Harbor访问有异常情况时,可以在Harbor目录执行docker-compose ps,查看相关进程是否处于UP状态。
  2. 不要随便执行installprepare脚本,会重置配置,如果执行了,记得修改common中Nginx的配置。(参考上文提到的)

总结

第一次搭建 Harbor 的过程是繁琐的,很可能遇到许多奇奇怪怪的问题(大多数是流程做错了),但只要搭过一次,就很顺利了。
这里的 Harbor 是单点,后面假设有时间的话,介绍下如何搭建 HA 版本的 Harbor。

参考