Skip to content

为什么要将harbor 反向代理 ?

因为服务器上不光有harbor 一个服务,其他服务都是由nginx作为代理 (80、443)转发到后端的服务。

因此harbor 也需要进行反向代理。

配置Nginx 代理 Harbor

bash
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端口

bash
firewall-cmd --add-port=11443/tcp --permanent && firewall-cmd --reload

若使用自签名证书,需将CA证书复制到Docker信任目录:

bash
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服务器的地址?

bash
[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地址:

bash
curl -I https://repository.xinn.cc/v2/

响应头中将包含类似字段:

bash
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安装目录

bash
cd /app/harbor

修改harbor.yml,找到以下参数并替换为代理域名

yaml
external_url: https://repository.xinn.cc  # 关键:设置外部访问地址
token_service_url: https://repository.xinn.cc/service/token  # 显式指定Token服务地址

确保Harbor在响应中返回repository.xinn.cc作为服务地址

2.重新部署Harbor

bash
# 停止Harbor
docker-compose down
# 应用配置并重启
./prepare   # 重新生成配置
docker-compose up -d

3.允许Docker访问非HTTPS仓库(可选)

若代理使用自签名证书或未启用HTTPS,需修改Docker配置:

json
# 编辑Docker服务文件
vim /etc/docker/daemon.json

{
  "insecure-registries": ["repository.xinn.cc"]
}

重启Docker生效

bash
systemctl restart docker

4.验证配置生效

检查Token服务地址

bash
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. 再次登录

✅登录成功!

bash
[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中的原始镜像可能无法正常拉取,可以使用以下脚本将原始镜像进行批量替换,替换为阿里云镜像。

bash
#!/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

脚本替换前

bash
[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

脚本替换后

bash
[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

Updated at: