Author:晴风
Date:2024-06-25

因为众所周知的原因 ,国内机器无法正常拉取Docker hub上的镜像,结合网上的教程,这里介绍两种方法来解决,实测可用。

一、 使用Cloudflare Wokers代理

该方法无需海外服务器,但需要有一个域名,且域名解析已托管至Cloudflare,该方法建议仅限个人使用,请勿滥用Cloudflare。

Workers提供serverless部署方案,服务会运行在Cloudflare的服务器中,我们无需关注具体会部署在哪里。

实现思路即是使用Workers将对registry的访问使用Cloudflare的服务器进行代理,并绑定到子域名中。这种方法早已有大佬想到,我们拿来使用即可,项目为ciiiii/cloudflare-docker-proxy: A docker registry proxy run on cloudflare worker. (github.com)

部署过程

部署项目到Workers

这里介绍使用Cloudflare提供的快速部署,需要有Github账号,进入项目链接,直接点击README中的Deploy to Cloudflare Workers按钮,按照步骤完成部署。

  1. 授权:点击 Authorize Workers ,登录Github账号并进行授权。
  2. 配置Cloudflare账号:选择 I have an account ,这里需要提供Account IDAPI Token。根据提示,访问Workers Dashboard页面,在登录账号后可获取账户ID;访问My Profile页面,创建API令牌,选择 编辑 Cloudflare Workers 模板,账户和区域选择 所有账户所有区域 即可,完成得到API令牌。
  3. Fork项目:点击 Fork the repository 按钮,根据提示启用Workflows,点击 Workflows enabled 进入下一步。
  4. 部署:根据提示,直接点击Deploy部署到Workers,提示Project is deployed Successful即部署成功,点击 Successful 查看所有Workflows,点击 GitHub repo 进入查看Fork的项目。
配置域名
  1. 修改Fork项目的配置:修改项目下的 src/index.js 文件,修改 routes自己的子域名,这里可以保留需要的代理,我只保留docker,提交修改。查看 Actions 中所有Workflows,会发现新增一个新的Workflows:Update index.js,并自动执行,等待执行完成。

    const routes = {
      // production
      "docker.example.com": dockerHub,
      //"quay.example.com": "https://quay.io",
      //"gcr.example.com": "https://gcr.io",
      //"k8s-gcr.example.com": "https://k8s.gcr.io",
      //"k8s.example.com": "https://registry.k8s.io",
      //"ghcr.example.com": "https://ghcr.io",
      //"cloudsmith.example.com": "https://docker.cloudsmith.io",
    
      // staging
      "docker-staging.example.com": dockerHub,
    };
  1. 新增DNS解析:登录Cloudflare,进入上一步配置的子域名所属域名下,点击右侧 DNS ,新增一个A类型记录,名称docker,地址192.0.2.1,默认代理,保存;再新增一个名称为docker-staging的记录,其它配置一样。
  2. 添加Workers路由:点击右侧的 Workers路由添加路由 ,路由填写 docker.example.com/ ,Workers选择 cloudflare-docker-proxy ;再新增一个路由,路由填写 docker-staging.example.com/ ,Workers选择 cloudflare-docker-proxy-staging
验证

浏览器访问 https://docker.example.com,结果与访问 https://registry-1.docker.io 一致,那至少成功了一半。

测试使用指定源拉取镜像

docker pull docker.example.com/nginx
或
docker pull docker.example.com:port/library/nginx

测试通过后可以配置到docker配置文件中。

二、 使用Nginx代理

该方法需要海外服务器,域名可选,推荐使用该方法。

思路即是用境外服务器上的Nginx来代理官方的registry。

部署过程

有NginxProxyManager的话仅配置方便一些,一样要自定义Nginx配置,默认配置无效。没有也可以通过直接修改Nginx配置来实现,以下方式二选一。

使用NginxProxyManager配置

添加代理服务,域名 填ip或者子域名,协议 https,转发主机/IP registry-1.docker.io,转发端口 443。

在高级中添加自定义Nginx配置,填入以下内容

location / {
    # Docker hub 的官方镜像仓库
    proxy_pass https://registry-1.docker.io;  
    proxy_set_header Host registry-1.docker.io;
    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_buffering off;
    # 转发认证相关
    proxy_set_header Authorization $http_authorization;
    proxy_pass_header  Authorization;
    # 对 upstream 状态码检查,实现 error_page 错误重定向
    proxy_intercept_errors on;
    recursive_error_pages on;
    # 根据状态码执行对应操作,以下为381、302、387状态码都会触发
    error_page 301 302 307 = @handle_redirect;
}
location @handle_redirect {
    resolver 1.1.1.1;
    set $saved_redirect_location '$upstream_http_location';
    proxy_pass $saved_redirect_location;
}

可选启用ssl,保存即可。

修改Nginx配置

根据实际情况,修改nginx的配置文件或者添加vhost配置,并在server下添加以下内容

与使用NginxProxyManager配置的内容一致

重启nginx。

验证

看使用Cloudflare Wokers代理部分,此处略。

附、 修改Docker配置

编辑 /etc/docker/daemon.json 文件,加入以下配置

{
  "registry-mirrors": ["https://<域名>[:端口]"]
}

例如

{
    "registry-mirrors": [
        "https://docker.example.com",
        "https://docker-nginx.example.com:8443"
    ]
}

重启Docker服务

systemctl restart docker

进行拉取镜像测试

docker pull chishin/nginx-proxy-manager-zh