Harbor除了可以用来搭建私有容器镜像仓库,安全审查等功能外,还能添加外部仓库进行操作,例如Docker Hub、GitHub GHCR等。

在我经常接触到的一些场景下,例如项目需要在大陆的云服务器上临时部署一个打包成容器的项目,可能会因为网络环境不太好拉取这个镜像,24年那会因为监管要求,大部分高校和机构的Docker Hub镜像站被下架,其他小镜像站可用性又不好说,于是我自己搞了一个私有镜像站来反代这些不太好访问的镜像源,通过CDN进行缓存和加速。

准备

  • 安装和配置好Harbor,让它处于一个可用状态(这一节请自行查看Harbor官方的教程,很简单,执行个脚本的事情)。

  • 确保安装Harbor的机器网络环境可以访问你要反代的镜像仓库。

  • 你有对应镜像仓库的凭据,例如GitHub用户名和Access Token(用于GHCR)

添加镜像仓库

  1. 在Harbor的镜像管理>仓库管理中,新建目标

  2. 在提供者处选择上游镜像仓库,例如Docker Hub,GHCR,或者其他自建的Docker Registry

  3. 在对应的平台获取你的访问令牌,GHCR直接用GitHub令牌即可(需要packages:read/write),Docker Hub直接在账户管理处生成

配置完成后,点击测试连接,返回成功后即可添加

添加项目

在添加了镜像仓库后,我们还需要添加一个项目,来让我们的镜像仓库可以通过Harbor的地址直接拉取

在项目管理处新建项目,项目名称可以随意取,这个名称用于后续拉取使用,然后开启镜像代理,这时候就可以在下拉框找到刚才添加的镜像仓库了,假定我们的项目名是dockerhub

如果是私人或者自己团队用,不建议公开,因为流量成本很高;如果是当大善人那请随意。

按照提示添加好项目后,我们就可以通过这个项目进行镜像拉取了

拉取测试

假如我们要拉取redis,我们的Harbor实例在reg.domain.com上

在使用docker-cli或者podman等工具配置好身份验证后,使用reg.domain.com/dockerhub/redis[:tag]替换源镜像拉取即可

推送

如果对应镜像仓库的Access Token有写权限,你还可以把Harbor配置为中转仓库,使用Harbor将镜像推送至目标平台,这里就不再说明如何操作。

更换默认镜像

正常情况下,通过修改/etc/docker/daemon.json (Docker)或/etc/containers/registries.conf(Podman)可以让容器镜像拉取时走代理源,但是目前Harbor并不支持多FQDN,也就是说,如果镜像站为https://reg.liteyuki.icu/dockerhub是不能被配置为容器镜像站的,它会被解析为https://reg.liteyuki.icu,假如你在拉取ubuntu/postgres时,本应该拉取reg.liteyuki.icu/dockerhub/ubuntu/postgres:latest,实际上拉取的是reg.liteyuki.icu/ubuntu/postgres:latest,这种情况下自然会失败,然后fallback到默认地址又不一定连得上。

Harbor有关此问题解决的提案issue,但是被拒绝:https://github.com/goharbor/harbor/issues/20849

目前参考了一个方法:https://blog.csdn.net/catoop/article/details/141125757

修改Nginx配置,新建一个dockerhub.reg.liteyuki.icu指向源站,具体需要修改/v2和/service的路由

location ~ ^/v2/(?<path>.*)$ {
    if ($path != "") {
        set $path "dockerhub/$path";  # 修改为你的反代项目名称
    }

    proxy_pass            https://reg.liteyuki.icu/v2/$path;  # 修改为你的harbor主域
    proxy_cache           off;
    proxy_set_header      Host                            $http_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;
    proxy_read_timeout    900;
    proxy_hide_header     Www-Authenticate;
}

location ~ ^/service/ {
    if ($args ~* "^(.*)(scope=repository%3A)(.*)$") {
        set $args "$1$2dockerhub%2F$3";  # 修改为你的反代项目名称
    }
    proxy_pass            https://reg.liteyuki.icu$uri$is_args$args;  # 修改为你的harbor主域
    proxy_cache           off;
    proxy_set_header      Host                            $http_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;
    proxy_read_timeout    900;
}