部署harbor过程
环境部署
需要一台虚拟机或是物理机,安装docker。
签发证书
创建目录/data/ssl,然后在该目录下进行下列操作。
生成CA证书。首先生成一个自签名的 CA 证书 (ca.pem) 和私钥 (ca.key)。这个自签名证书是整个信任链的起点,它相当于你自己设立了一个信任的基础。任何客户端如果要信任 Harbor 的证书 (harbor.pem),必须首先信任 CA 证书 (ca.pem)。因此,需要将 ca.pem 安装到客户端的信任存储中(例如,浏览器信任的根证书列表,或系统的受信任证书列表)。
openssl genrsa -out ca.key 3072
openssl req -new -x509 -days 3650 -key ca.key -out ca.pem
最开始生成的 CA 证书 确实是 自签名 的,也就是说,我自己生成了一个 CA 证书,并用它去签发后续的域名证书。-x509
:指示 OpenSSL 生成一个自签名的证书而不是证书请求 (CSR),因为 CA 需要自签名证书来证明其身份。
openssl genrsa -out harbor.key 3072
#生成一个 3072 位的 key,也就是私钥
openssl req -new -key harbor.key -out harbor.csr
#生成一个证书请求
签发域名证书:
x509 -req:表示使用 harbor.csr 来生成最终的证书。
-in harbor.csr:指定输入的证书签名请求文件为 harbor.csr。
-CA ca.pem:指定 CA 的证书文件是 ca.pem,用来签署该域名证书。
-CAkey ca.key:使用 CA 的私钥 ca.key 进行签名。
-CAcreateserial:生成 ca.srl 文件以存储 CA 的序列号。每次签发证书时,序列号都会递增,确保每个证书都是唯一的。
-out harbor.pem:生成的 Harbor 域名证书将存储在 harbor.pem 文件中。
-days 3650:生成的证书有效期为 3650 天(约 10 年)。
openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out harbor.pem -days 3650
填写以下信息,为空的就直接回车
随后显示以下代码,则签发成功。
[root@harbor ssl]# openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out harbor.pem -days 3650
Signature ok
subject=/C=CH/ST=BJ/L=BJ/O=Default Company Ltd/CN=harbor
Getting CA Private Key
安装harbor
从网站下载harbor的离线安装包。
创建目录/data/install,将harbor安装包上传到该目录。将harbor安装包解压后,进入harbor目录下,可以看到这里有一个叫harbor.yml.tmpl的文件,这个是harbor提供的一个模板文件,用来给用户修改的,实际上harbor程序识别的配置文件名称是harbor.yml。因此我们复制这个模板文件为harbor.yml文件,并进行修改。
harbor harbor-offline-installer-v2.11.1.tgz
[root@harbor install]# cd harbor
[root@harbor harbor]# ls
common.sh harbor.v2.11.1.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
由于上面我们的操作过程都是生成了基于harbor的密钥,而且我的主机名称也修改为harbor,所以这些配置都要写入harbor的config文件中,按照以下格式进行修改:
这两个地方分别修改为harbor,以及存放harbor证书和私钥的地方,也就是我们刚才生成harbor.pem和harbor.key的地方。将url_protocol改为https。
这里也写了harbor的默认密码,为Harbor12345。如果要修改的话可以自己修改。
随后执行以下命令进行镜像扫描,发现由于docker compose版本过低,发生错误。
[root@harbor harbor]# ./install.sh --with-notary --with-clair[Step 0]: checking installation environment ...
...
[Step 4]: starting Harbor ...
ERROR: client version 1.22 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version
安装docker compose
下载docker compose的2.21版本,并且重新执行harbor的镜像扫描命令。
sudo curl -L "https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-compose
但是以上命令好久都没有下载下来。打开docker compose的官方网站,进行下载。
将该文件上传到虚拟机的/usr/bin目录下,可以看到这个目录下还有docker等其他配置文件。
给这个文件进行重命名为docker-compose,随后查看docker compose的版本,发现系统成功识别。随后给docker-compose赋予权限。
[root@harbor bin]# sudo chmod +x /usr/bin/docker-compose
[root@harbor bin]# docker-compose --version
Docker Compose version v2.28.0
接下来重新进行harbor的镜像扫描,发现harbor启动成功(最后一行)。
[root@harbor harbor]# ./install.sh --with-trivy[Step 0]: checking if docker is installed ...Note: docker version: 26.1.4[Step 1]: checking docker-compose is installed ...Note: Docker Compose version v2.27.1[Step 2]: loading Harbor images ...
fa65d0b345aa: Loading layer [==================================================>] 40.5MB/40.5MB
...
Loaded image: goharbor/trivy-adapter-photon:v2.11.1[Step 3]: preparing environment ...[Step 4]: preparing harbor configs ...
prepare base dir is set to /data/install/harbor
Generated configuration file: /config/portal/nginx.conf
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/log/rsyslog_docker.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/registryctl/config.yml
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
loaded secret from file: /data/secret/keys/secretkey
Successfully called func: create_root_cert
Generated configuration file: /config/trivy-adapter/env
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir[Step 5]: starting Harbor ...? ----Harbor has been installed and started successfully.----
可以看到harbor启动的所有container。分别为nginx、harbor-jobservice、trivy-adapter、harbor-core、registryctl、redis、harbor-portal、harbor-db、registry、harbor-log。
[root@harbor harbor]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d4e0644e22c goharbor/nginx-photon:v2.11.1 "nginx -g 'daemon of…" 48 seconds ago Up 46 seconds (healthy) 0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp nginx
e7b311d298d3 goharbor/harbor-jobservice:v2.11.1 "/harbor/entrypoint.…" 48 seconds ago Up 43 seconds (healthy) harbor-jobservice
b7e7273c632e goharbor/trivy-adapter-photon:v2.11.1 "/home/scanner/entry…" 48 seconds ago Up 46 seconds (healthy) trivy-adapter
bbc9e9629edc goharbor/harbor-core:v2.11.1 "/harbor/entrypoint.…" 48 seconds ago Up 46 seconds (healthy) harbor-core
db277f383a03 goharbor/harbor-registryctl:v2.11.1 "/home/harbor/start.…" 48 seconds ago Up 47 seconds (healthy) registryctl
d3f93ec27671 goharbor/redis-photon:v2.11.1 "redis-server /etc/r…" 48 seconds ago Up 47 seconds (healthy) redis
6ae604f4a309 goharbor/harbor-portal:v2.11.1 "nginx -g 'daemon of…" 48 seconds ago Up 47 seconds (healthy) harbor-portal
ac8c9e26a640 goharbor/harbor-db:v2.11.1 "/docker-entrypoint.…" 48 seconds ago Up 47 seconds (healthy) harbor-db
f6502fa65973 goharbor/registry-photon:v2.11.1 "/home/harbor/entryp…" 48 seconds ago Up 47 seconds (healthy) registry
d9ff8e39b1ce goharbor/harbor-log:v2.11.1 "/bin/sh -c /usr/loc…" 48 seconds ago Up 47 seconds (healthy) 127.0.0.1:1514->10514/tcp harbor-log
修改hosts文件
进入本机hosts文件,将harbor的地址加入hosts,标明为harbor。这里的主机名称harbor应该和harbor.cfg文件里配置的相同。
因为我们已经成功部署了harbor,而且修改了hosts文件,此时在浏览器输入https://harbor,可以看到如下界面:
这里的账号是admin,密码是写在harbor.cfg里的Harbor12345,如果在那个文件修改过的,这里就输入相应密码。
以上看到的是Harbor 提供的用户友好的web控制台,用户可以通过浏览器访问这个界面,进行仓库管理、用户管理、权限设置、查看镜像、删除镜像等等。但是要真的推送和拉取镜像,还要在harbor所在的虚拟机或物理机进行操作。
设置insecure-registries
docker需要通过命令行登录到 Harbor 仓库,这样就可以使用docker push和docker pull命令与 Harbor 进行交互。insecure registries 在 Docker 的配置中用于指定允许不安全(未加密)的 Docker 注册表。这意味着 Docker 客户端将允许与这些注册表通过 HTTP(而非 HTTPS)进行通信,忽略证书的验证。在配置中,"insecure-registries":["192.168.244.131"]
这行表示 Docker 将允许与我的 Harbor 实例(通过 HTTP 进行通信,而不要求使用 HTTPS 或证书。
通常,Harbor 被配置为使用 HTTPS 进行安全通信,但如果没有设置有效的 TLS 证书或暂时使用 HTTP 来简化配置,需要在 Docker 客户端中将这个 Harbor 服务器列为 "不安全" 的注册表,这样 Docker 才会允许不通过 HTTPS 登录和推拉镜像。有了这一行配置后,Docker 客户端就知道无需检查 192.168.244.131
的安全证书,从而可以通过 HTTP 登录到的 Harbor 实例。
进行如下操作,在/etc/docker/daemon.json文件中加入一行:
"insecure-registries":["192.168.40.132"],
[root@harbor docker]# cat daemon.json
{
"registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.dockercn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hubmirror.c.163.com","http://qtid6917.mirror.aliyuncs.com"],
"exec-opts":["native.cgroupdriver=systemd"],
"log-driver":"json-file",
"log-opts": {"max-size": "100m"},
"insecure-registries":["192.168.40.132"],
"storage-driver":"overlay2"}
随后重启docker,使得配置生效:systemctl daemon-reload && systemctl restart docker
值得注意的是,原本的
"storage-opts": [
"overlay2.override_kernel_check=true"
]
字段已经弃用,加上这个docker的运行会出错。
随后可以通过docker来登录harbor;
[root@harbor harbor]# docker login 192.168.244.131
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
上传/下载镜像
在harbor虚拟机上下载一个tomcat镜像:xianchao/tomcat-8.5-jre8:v1
[root@harbor ~]# docker load -i xianchao_tomcat.tar.gz
f1b5933fe4b5: Loading layer [==================================================>] 5.796MB/5.796MB
9b9b7f3d56a0: Loading layer [==================================================>] 3.584kB/3.584kB
edd61588d126: Loading layer [==================================================>] 80.28MB/80.28MB
48988bb7b861: Loading layer [==================================================>] 2.56kB/2.56kB
8e0feedfd296: Loading layer [==================================================>] 24.06MB/24.06MB
aac21c2169ae: Loading layer [==================================================>] 2.048kB/2.048kB
Loaded image: xianchao/tomcat-8.5-jre8:v1
[root@harbor ~]# docker images | grep tomcat
xianchao/tomcat-8.5-jre8 v1 8b8b1eb786b5 5 years ago 106MB
登录harbor的网页端,创建一个公开的项目test。
点击进入test项目,并复制推送命令中的镜像标记命令。
格式为:docker tag SOURCE_IMAGE[:TAG] harbor/test/REPOSITORY[:TAG],可以看到这里的harbor是我们的hostname,test是项目的名称,而后面的repository和tag是可以自己发挥的。在这里我们将之前的tomcat的镜像进行一个标记。
[root@harbor ~]# docker tag xianchao/tomcat-8.5-jre8:v1 harbor/test/tomcat:v1
随后用push命令进行推送
[root@harbor ~]# docker push harbor/test/tomcat:v1
The push refers to repository [docker.io/harbor/test/tomcat]
Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
但是推送失败,从信息来看尝试将镜像推送到docker的官方镜像仓库中。我重新进行tag和推送,不使用harbor的主机名称,而使用harbor的地址,发现推送成功。
[root@harbor ~]# docker tag xianchao/tomcat-8.5-jre8:v1 192.168.244.131/test/tomcat:v1
您在 /var/spool/mail/root 中有新邮件
[root@harbor ~]# docker push 192.168.244.131/test/tomcat:v1
The push refers to repository [192.168.244.131/test/tomcat]
aac21c2169ae: Pushed
8e0feedfd296: Pushed
48988bb7b861: Pushed
edd61588d126: Pushed
9b9b7f3d56a0: Pushed
f1b5933fe4b5: Pushed
v1: digest: sha256:3998c88afb2c2751c18db3fb0b45cb4f8bb1d575591a96dcd9f071ce12651242 size: 1574
查看网页,发现镜像已经上传成功。
此时删除本地镜像, 然后从harbor仓库拉取,发现拉取成功。如下删掉了所有tomcat镜像:
[root@harbor ~]# docker rmi -f 192.168.244.131/test/tomcat:v1
Untagged: 192.168.244.131/test/tomcat:v1
Untagged: 192.168.244.131/test/tomcat@sha256:3998c88afb2c2751c18db3fb0b45cb4f8bb1d575591a96dcd9f071ce12651242
[root@harbor ~]# docker images | grep tomcat
xianchao/tomcat-8.5-jre8 v1 8b8b1eb786b5 5 years ago 106MB
[root@harbor ~]# docker rmi -f xianchao/tomcat-8.5-jre8:v1
Untagged: xianchao/tomcat-8.5-jre8:v1
Deleted: sha256:8b8b1eb786b54145731e1cd36e1de208d10defdbb0b707617c3e7ddb9d6d99c8
Deleted: sha256:d207c160809b75dcaefae2c541ffaf53fb9ae62e7df25760c05b2193a33c5bfe
Deleted: sha256:f7ed7c99b0d3e32de6af857d1160d050854b099f496758365d1d67fb1f85d20d
Deleted: sha256:9bf169c4c2a7cf68668dcf4d84369757891189d182ed6ce53aa010b5cde2859c
Deleted: sha256:aba8cd4318a8a15f59f305368e49cc3bbd0d6d72171a0b24d08cc00513b14ef4
Deleted: sha256:c318fbba92645a83843c387bd78497e7b143ecc7f5ed99dcb7d38fc62442c02a
Deleted: sha256:f1b5933fe4b5f49bbe8258745cf396afe07e625bdab3168e364daf7c956b6b81
您在 /var/spool/mail/root 中有新邮件
[root@harbor ~]# docker images | grep tomcat
随后拉取:
[root@harbor ~]# docker pull 192.168.244.131/test/tomcat:v1
v1: Pulling from test/tomcat
e7c96db7181b: Pull complete
f910a506b6cb: Pull complete
b6abafe80f63: Pull complete
d8c966ddef98: Pull complete
07e652475ee6: Pull complete
c42103cfa50f: Pull complete
Digest: sha256:3998c88afb2c2751c18db3fb0b45cb4f8bb1d575591a96dcd9f071ce12651242
Status: Downloaded newer image for 192.168.244.131/test/tomcat:v1
192.168.244.131/test/tomcat:v1
补充
如果要使用habor/test的地址推送,需要在docker 的deamon.json文件中设置insecure-registries为habor,同时docker login的时候也需要是harbor,而不是地址。
[root@harbor harbor]# cat /etc/docker/daemon.json
{
"insecure-registries":["192.168.244.131","harbor"],
"registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.dockercn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hubmirror.c.163.com","http://qtid6917.mirror.aliyuncs.com"],
"exec-opts":["native.cgroupdriver=systemd"],
"log-driver":"json-file",
"log-opts": {"max-size": "100m"},
"storage-driver":"overlay2"}
执行docker login的时候发生错误,报502bad gateway。
修改harbor的yml文件,增加一个external_url字段。
随后重启harbor:
docker-compose down
docker-compose up -d
d
代表 "detached" 模式。这意味着容器将在后台运行,而不会阻塞你的终端。使用 -d
后,你可以继续在终端中执行其他命令,而不必等待容器的输出。
随后发现harbor可以通过hostname和ip登录。
root@harbor harbor]# docker login https://harbor
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded[root@harbor harbor]# docker login harbor
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
您在 /var/spool/mail/root 中有新邮件
[root@harbor harbor]# docker login 192.168.244.131
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
但是进行镜像拉取和上传的时候仍需要使用ip,初步判断可能是hostname取名太过简单,docker push会自动加上docker.io的请求头。一般的hostname可能比较复杂,比如example.com这种,可能就不会受影响,但是本人目前没有试验过。
我部署的harbor版本较新,里面的两个container,notary-server 和clair 服务需要额外的配置文件和数据库连接,但是这些我都没有配置,因此这两个container会报错,但是这两个服务本身并不是harbor的核心服务,所以如果发现报错,也不用担心。