为什么要将harbor 反向代理 ?
因为服务器上不光有harbor 一个服务,其他服务都是由nginx作为代理 (80、443)转发到后端的服务。
因此harbor 也需要进行反向代理。

配置Nginx 代理 Harbor
server {
listen 443 ssl;
server_name repository.xinn.cc;
location / {
proxy_pass https://10.1.18.52:11443; # 指向实际Harbor端口
proxy_set_header Host $host; # 传递代理域名
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}开放防火墙端口
确认服务器防火墙放行11443端口
firewall-cmd --add-port=11443/tcp --permanent && firewall-cmd --reload若使用自签名证书,需将CA证书复制到Docker信任目录:
mkdir -p /etc/docker/certs.d/repository.xinn.cc
cp ca.crt /etc/docker/certs.d/repository.xinn.cc/ca.crt测试上传镜像
此时出现connect: connection refused 问题,发现我们已经把repository.xinn.cc转发到了10.1.18.52:11443,但是登录时提示https://10.1.18.52:11443/service/token,为什么没有走代理后的地址。而是直接返回了后端Harbor服务器的地址?
[root@OpenEuler2203 ~]# docker login https://repository.xinn.cc/
Username: SDCSFK
Password:
Error response from daemon:
Get "https://repository.xinn.cc/v2/":
Get "https://10.1.18.52:11443/service/token?account=SDCSFK&client_id=docker&offline_token=true&service=harbor-registry":
dial tcp 10.1.18.52:11443: connect: connection refused问题原因
Docker在登录的时候,不仅需要连接仓库,还需要获取访问令牌(token),这个token是通过请求Harbor的token服务来获取的。
Docker Registry的授权机制是:当你尝试登录时,Registry会返回401未授权错误,并告诉客户端去哪里获取token(通过WWW-Authenticate响应头)。
问题核心在于Harbor的Token服务配置未适配反向代理域名。
当Docker访问https://repository.xinn.cc时,虽然请求被代理到https://10.1.18.52:11443,但Harbor返回的Token服务地址仍是原始服务地址,导致Docker直接访问后者失败。
验证现象
执行以下命令检查Harbor返回的Token地址:
curl -I https://repository.xinn.cc/v2/响应头中将包含类似字段:
HTTP/2 401
server: openresty
date: Sat, 18 Oct 2025 11:22:25 GMT
content-type: application/json; charset=utf-8
content-length: 76
docker-distribution-api-version: registry/2.0
set-cookie: sid=a63df123sda5536105baabsddq238145851; Path=/; HttpOnly
www-authenticate: Bearer realm="https://10.1.18.52:11443/service/token",service="harbor-registry"
x-request-id: fa12w1a3-5rf2-420d-96ee-ec2339618b40可以看到Docker会直接访问10.1.18.52:11443而非代理域名。
解决方案
1.修改Harbor配置文件
进入Harbor安装目录
cd /app/harbor修改harbor.yml,找到以下参数并替换为代理域名
external_url: https://repository.xinn.cc # 关键:设置外部访问地址
token_service_url: https://repository.xinn.cc/service/token # 显式指定Token服务地址确保Harbor在响应中返回repository.xinn.cc作为服务地址
2.重新部署Harbor
# 停止Harbor
docker-compose down
# 应用配置并重启
./prepare # 重新生成配置
docker-compose up -d3.允许Docker访问非HTTPS仓库(可选)
若代理使用自签名证书或未启用HTTPS,需修改Docker配置:
# 编辑Docker服务文件
vim /etc/docker/daemon.json
{
"insecure-registries": ["repository.xinn.cc"]
}重启Docker生效
systemctl restart docker4.验证配置生效
检查Token服务地址
curl -I https://repository.xinn.cc/v2/
HTTP/2 401
server: openresty
date: Sat, 18 Oct 2025 11:22:25 GMT
content-type: application/json; charset=utf-8
content-length: 76
docker-distribution-api-version: registry/2.0
set-cookie: sid=a63df06878231q11s23d2d1145851; Path=/; HttpOnly
www-authenticate: Bearer realm="https://repository.xinn.cc/service/token",service="harbor-registry"
x-request-id: fa2311a3-9bf2-4433d-96ee-ece12ds18b40观察返回头中的Www-Authenticate字段是否变为https://repository.xinn.cc/service/token
5. 再次登录
✅登录成功!
[root@OpenEuler2203 ~]# docker login https://repository.xinn.cc
Username: SDCSFK
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/#credential-stores
Login Succeeded批量替换harbor镜像脚本
由于网络问题docker-compose.yml中的原始镜像可能无法正常拉取,可以使用以下脚本将原始镜像进行批量替换,替换为阿里云镜像。
#!/bin/bash
# 定义原始镜像前缀和目标阿里云前缀
SOURCE_PREFIX="goharbor/"
TARGET_PREFIX="registry.cn-beijing.aliyuncs.com/xxk8s/"
# 检查docker-compose.yml文件是否存在
if [ ! -f docker-compose.yml ]; then
echo "错误: docker-compose.yml 文件不存在!"
exit 1
fi
# 执行替换操作
sed -i "s|image: ${SOURCE_PREFIX}|image: ${TARGET_PREFIX}|g" docker-compose.yml
# 验证替换结果
echo "替换完成,更新后的镜像配置:"
grep -E "image: ${TARGET_PREFIX}" docker-compose.yml
# 可选:重启服务(取消注释以下行以启用)
# docker-compose down && docker-compose up -d脚本替换前:
[root@openEuler2203-16 harbor]# cat docker-compose.yml | grep image
image: goharbor/harbor-log:v2.14.0
image: goharbor/registry-photon:v2.14.0
image: goharbor/harbor-registryctl:v2.14.0
image: goharbor/harbor-db:v2.14.0
image: goharbor/harbor-core:v2.14.0
image: goharbor/harbor-portal:v2.14.0
image: goharbor/harbor-jobservice:v2.14.0
image: goharbor/redis-photon:v2.14.0
image: goharbor/nginx-photon:v2.14.0脚本替换后:
[root@openEuler2203-16 harbor]# cat docker-compose.yml | grep image
image: registry.cn-beijing.aliyuncs.com/xxk8s/harbor-log:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/registry-photon:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/harbor-registryctl:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/harbor-db:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/harbor-core:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/harbor-portal:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/harbor-jobservice:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/redis-photon:v2.13.1
image: registry.cn-beijing.aliyuncs.com/xxk8s/nginx-photon:v2.13.1