方案 1:临时跳过 TLS 验证(测试环境适用,快速生效)
适合临时测试,无需修改 Harbor 服务端证书,仅在客户端配置「信任该 Harbor 为不安全仓库」:
客户端操作步骤(以 Ubuntu/Debian 为例,CentOS 操作一致):
编辑客户端 Docker 配置文件
打开 / 新建 Docker 守护进程配置文件daemon.json
:bash
sudo vim /etc/docker/daemon.json
写入以下内容(
192.168.31.19
替换为你的 Harbor IP):json
{ "insecure-registries": ["192.168.31.19"] // 允许客户端跳过该IP的TLS验证 }
重启客户端 Docker 服务
使配置生效:bash
sudo systemctl daemon-reload sudo systemctl restart docker
客户端重新登录 Harbor
此时 Docker 会忽略 TLS 证书格式问题,直接连接:bash
sudo docker login 192.168.31.19 # 输入Harbor管理员账号(admin)和密码,提示“Login Succeeded”即成功
停止 Harbor 服务
bash
cd ~/harbor # 进入Harbor安装目录 sudo docker compose down -v
生成带 SANs 的证书
创建证书目录:
sudo mkdir -p /etc/harbor/ssl && cd /etc/harbor/ssl
新建 SANs 配置文件
san.cnf
:bash
sudo vim san.cnf
写入内容(替换IP.1=192.168.31.19
为你的 Harbor IP):ini
[req] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn x509_extensions = req_ext [dn] C=CN ST=YourProvince L=YourCity O=YourCompany OU=YourDepartment CN=192.168.31.19 # 旧版CN(保留兼容) [req_ext] subjectAltName = @alt_names [alt_names] IP.1=192.168.31.19 # 关键:用SANs绑定Harbor IP(现代TLS要求)
生成私钥和证书:
bash
sudo openssl genrsa -out harbor.key 2048 sudo openssl req -new -x509 -key harbor.key -out harbor.crt -days 3650 -config san.cnf
服务端更新 Harbor 配置并重启
编辑
harbor.yml
指向新证书:bash
cd ~/harbor sudo vim harbor.yml
修改https
配置:yaml
https: port: 443 certificate: /etc/harbor/ssl/harbor.crt # 新证书路径 private_key: /etc/harbor/ssl/harbor.key # 新私钥路径
重新部署 Harbor:
bash
sudo ./prepare sudo docker compose up -d
第二步:客户端信任新证书(客户端机器上)
在客户端创建证书信任目录
目录名必须是「Harbor IP」(与服务端 IP 一致):bash
sudo mkdir -p /etc/docker/certs.d/192.168.31.19
从 Harbor 服务端复制新证书到客户端
用scp
把服务端的harbor.crt
复制到客户端(替换shitou
为服务端用户名):bash
sudo scp shitou@192.168.31.19:/etc/harbor/ssl/harbor.crt /etc/docker/certs.d/192.168.31.19/ca.crt
注意:客户端证书必须命名为
ca.crt
(Docker 默认读取该文件名)。
重启客户端 Docker 服务
bash
sudo systemctl daemon-reload sudo systemctl restart docker
客户端重新登录 Harbor
此时 Docker 会验证通过新证书,无 TLS 报错:bash
sudo docker login 192.168.31.19
shitou@shitou:sudo docker compose down -v
[sudo] password for shitou:
[+] Running 10/10
✔ Container harbor-jobservice Removed 1.1s
✔ Container nginx Removed 1.3s
✔ Container registryctl Removed 1.2s
✔ Container harbor-portal Removed 0.8s
✔ Container harbor-core Removed 0.7s
✔ Container registry Removed 1.1s
✔ Container harbor-db Removed 1.1s
✔ Container redis Removed 1.1s
✔ Container harbor-log Removed 11.0s
✔ Network harbor_harbor Removed 0.2s
shitou@shitou:~/harbor$ sudo mkdir -p /etc/harbor/ssl && cd /etc/harbor/ssl
shitou@shitou:/etc/harbor/ssl$ sudo vim san.cnf
shitou@shitou:/etc/harbor/ssl$ sudo openssl genrsa -out harbor.key 2048
shitou@shitou:/etc/harbor/ssl$ sudo openssl req -new -x509 -key harbor.key -out harbor.crt -days 3650 -config san.cnf
shitou@shitou:/etc/harbor/ssl$ cd ~/harbor
shitou@shitou:~/harbor$ sudo vim harbor.yml
shitou@shitou:~/harbor$ sudo ./prepare
prepare base dir is set to /home/shitou/harbor
Clearing the configuration file: /config/registry/passwd
Clearing the configuration file: /config/registry/config.yml
Clearing the configuration file: /config/registry/root.crt
Clearing the configuration file: /config/jobservice/env
Clearing the configuration file: /config/jobservice/config.yml
Clearing the configuration file: /config/portal/nginx.conf
Clearing the configuration file: /config/nginx/nginx.conf
Clearing the configuration file: /config/core/app.conf
Clearing the configuration file: /config/core/env
Clearing the configuration file: /config/log/logrotate.conf
Clearing the configuration file: /config/log/rsyslog_docker.conf
Clearing the configuration file: /config/registryctl/env
Clearing the configuration file: /config/registryctl/config.yml
Clearing the configuration file: /config/db/env
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
copy /data/secret/tls/harbor_internal_ca.crt to shared trust ca dir as name harbor_internal_ca.crt ...
ca file /hostfs/data/secret/tls/harbor_internal_ca.crt is not exist
copy to shared trust ca dir as name storage_ca_bundle.crt ...
copy None to shared trust ca dir as name redis_tls_ca.crt ...
loaded secret from file: /data/secret/keys/secretkey
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir
shitou@shitou:~/harbor$ sudo docker compose up -d
[+] Running 10/10
✔ Network harbor_harbor Created 0.3s
✔ Container harbor-log Started 2.7s
✔ Container registryctl Started 3.9s
✔ Container harbor-db Started 4.6s
✔ Container registry Started 4.5s
✔ Container redis Started 4.4s
✔ Container harbor-portal Started 3.8s
✔ Container harbor-core Started 4.6s
✔ Container nginx Started 6.1s
✔ Container harbor-jobservice Started 5.5s
shitou@shitou:~/harbor$
sudo docker pull nginx:1.29.1
1.29.1: Pulling from library/nginx
Digest: sha256:33e0bbc7ca9ecf108140af6288c7c9d1ecc77548cbfd3952fd8466a75edefe57
Status: Image is up to date for nginx:1.29.1
docker.io/library/nginx:1.29.1
shitou@aishitou:~$ sudo docker tag nginx:1.29.1 192.168.31.19/library/nginx:v1
shitou@aishitou:~$ sudo docker push 192.168.31.19/library/nginx:v1
The push refers to repository [192.168.31.19/library/nginx]
45c2d10807fb: Pushed
129b375526fc: Pushed
a0e5983a25a5: Pushed
2988603ca264: Pushed
39bc11fab520: Pushed
dab69e9f41e9: Pushed
eb5f13bce993: Pushed
v1: digest: sha256:6ef3c77a4ebfbf8f2cada3442839f0c49f7e5f643b5179ec4ed0f100ada8c9ae size: 1778
shitou@aishitou:~$ sudo docker pull tomcat:11.0.10
11.0.10: Pulling from library/tomcat
Digest: sha256:6df06d415fc022d911f43a6668167a6f74436b867d6b24e99492a386a0cd8339
Status: Image is up to date for tomcat:11.0.10
docker.io/library/tomcat:11.0.10
shitou@aishitou:~$ sudo docker tag tomcat:11.0.10 192.168.31.19/library/tomcat:11.0.10
shitou@aishitou:~$ sudo docker push 192.168.31.19/library/tomcat:11.0.10
The push refers to repository [192.168.31.19/library/tomcat]
5f70bf18a086: Pushed
b3e39a1a1009: Pushed
342586930e8a: Pushed
886ae98b49c1: Pushed
b975e904aaaf: Pushed
74b13d8a4515: Pushed
7ad9404c656d: Pushed
cd9664b1462e: Pushed
11.0.10: digest: sha256:e3fcbf18bc3d349134671c39bca6cf432ff008a90e90ce108f073ce2bf6ac48e size: 2201
shitou@aishitou:~$ sudo docker tag nginx:1.29.1 192.168.31.19/library/nginx:1.29.1
shitou@aishitou:~$ sudo docker tag nginx:1.29.1 192.168.31.19/library/nginx:1.29.1
shitou@aishitou:~$ sudo docker push 192.168.31.19/library/nginx:1.29.1
The push refers to repository [192.168.31.19/library/nginx]
45c2d10807fb: Layer already exists
129b375526fc: Layer already exists
a0e5983a25a5: Layer already exists
2988603ca264: Layer already exists
39bc11fab520: Layer already exists
dab69e9f41e9: Layer already exists
eb5f13bce993: Layer already exists
1.29.1: digest: sha256:6ef3c77a4ebfbf8f2cada3442839f0c49f7e5f643b5179ec4ed0f100ada8c9ae size: 1778
shitou@aishitou:~$