记录我的一些生活写照、无聊的牢骚、内心世界的活动 注册 | 登陆

无障碍访问 Docker Hub 的各种方法总结

无障碍访问 Docker Hub 的各种方法总结(自建 registry、Cloudflare 加速、Nginx 反代、代理 Docker 网络)
最近 Docker Hub 被屏蔽,各大镜像站关闭,想必很多人都遇到了无法拉取镜像的问题。本文将告诉你们继续使用 Docker Hub 的各种方法,助你解决开发/部署中面临的麻烦。
自建 registry
Docker 官方提供了 registry 镜像,这是最标准的搭建 mirror 的方法。你需要一个海外的服务器,通过 Docker Compose 部署。首先创建 docker-compose.yml 文件: 
XML/HTML代码
  1. services:
  2.   server:
  3.     image: registry
  4.     restart: always
  5.     ports:
  6.       - 5000:5000
  7.     volumes:
  8.       - ./config.yml:/etc/docker/registry/config.yml
  9.       - ./storage:/var/lib/registry
假定放在服务器的 docker/registry 目录。先不要部署,我们还需要在此目录创建 config.yml 文件:
XML/HTML代码
  1. version: 0.1
  2.  
  3. proxy:
  4.   remoteurl: https://registry-1.docker.io
  5. log:
  6.   level: debug # <- 如果部署后测试没问题,请改为 info
  7. http:
  8.   addr: 0.0.0.0:5000
  9. cache:
  10.   blobdescriptor: inmemory
  11. storage:
  12.   filesystem:
  13.     rootdirectory: /var/lib/registry
现在执行 docker compose up -d 部署即可。
XML/HTML代码
  1. docker run --name docker-proxy --restart always -p 5000:5000 -v ./config.yml:/etc/docker/registry/config.yml -v ./storage:/var/lib/registry registry
严格来说当前的 registry 镜像只是一个 mirror 程序,真正意义上的 registry 是 Harbor 这种可以存储和管理私有镜像的独立仓库。
测试部署
尝试访问这个服务,正常来讲你会看到一个空白页面。这仅表示服务可以访问,不能表示成功。
进一步访问 /v2/library/node/manifests/20 这个路径,这相当于手动调用此 mirror 的 API。如果正确会下载 node:20 这个镜像的 Manifest 文件,否则会显示 API 的错误响应。
修改 Docker 配置
编辑 /etc/docker/daemon.json 文件,加入以下配置:
XML/HTML代码
  1. {
  2.   "registry-mirrors": ["http://<YOUR_SERVER_HOST>:5000"]
  3. }
记得重启 Docker 服务,让配置生效。
有些人可能会发现,这和常见的国内 Docker Hub 加速器的配置方法一样。因为 Docker Hub 的镜像站实际上部署的就是 registry 程序,或与之类似的东西,或反向代理。
测试效果
执行 docker pull node:20 命令,尝试下载一个镜像。镜像下载完成后,进入服务器部署目录的 storage 文件夹,你应该会看到这样的结构:
XML/HTML代码
  1. storage/  
  2. ├── docker  
  3. │   └── registry  
  4. │       └── v2  
  5. │           ├── blobs  
  6. │           │   └── sha256  
  7. │           │       ├── 0e  
  8. │           │       ├── 18  
  9. │           │       ├── 48  
  10. │           │       ├── 51  
  11. │           │       ├── 7e  
  12. │           │       ├── 86  
  13. │           │       ├── ae  
  14. │           │       ├── c9  
  15. │           │       ├── ca  
  16. │           │       ├── ee  
  17. │           │       ├── f7  
  18. │           │       └── ff  
  19. │           └── repositories  
  20. │               └── library  
  21. │                   └── node  
  22. └── scheduler-state.json  
这表示服务器正确的缓存了镜像的信息和 blobs 到本地,下次拉取同一个镜像服务器就不会再走 Docker Hub 了。
registry 程序的配置内容还有很多,此处仅提供一个最简化的配置。更多请参考这里
Cloudflare Workers 代理
如果你没有服务器,你还可以利用 Cloudflare 来代理。Workers 是 Cloudflare 提供的 Serverless(无服务器)方案,实际上部署到 Workers 的程序会在 Cloudflare 自己的服务器上运行。你需要一个域名,且被 Cloudflare 托管。
我们编写一个将 Workers 的访问请求代理到 registry 的简单程序,就相当于把 Cloudflare 服务器做成反向代理了。已经有人写好了这样的程序,仓库地址:ciiiii/cloudflare-docker-proxy。访问此 Workers 应用的部署链接,按步骤分别连接上 GitHub 和 Cloudflare,它将自动为你 fork 仓库、启用 Actions 并部署到 Workers。
默认情况下部署会失败,你需要修改配置的域名。克隆 fork 后的仓库到本地,用编辑器批量替换 libcuda.so 为你自己的域名。最后提交修改触发 GitHub Actions,部署成功后 Workers 就能直接使用了。
测试 Workers
首先访问你的 Workers 中配置的域名,例如 docker.your.domain,如果得到的响应和访问 https://registry-1.docker.io 一模一样,就表示代理成功了。接下来,按照修改 Docker 配置章节设置 registry-mirrors 即可。
这个 Workers 程序还包含了对 K8S、ghcr 等的代理配置,默认会一并部署上。具体可以自行查阅仓库说明以及代码(非常简单,只是请求的代理而已)。
此方案建议用于个人,因为免费的 Workers 请求次数/流量有限,不适合公司内部大规模使用。并且 Cloudflare 的服务器访问速度比较慢,只是勉强能用。
Nginx 代理
此章节介绍的不是对自建 registry 的反向代理,而是对 Docker Hub 官方 registry 地址的代理。相当于搭建了一个无缓存功能的镜像站。在服务器上安装 Nginx 并添加以下配置片段:
 
XML/HTML代码
  1. location / {
  2.         client_max_body_size 1024M;
  3.         proxy_pass https://registry-1.docker.io:443;
  4.         proxy_set_header Authorization $http_authorization;
  5.         proxy_pass_header Authorization;
  6.         proxy_redirect https://registry-1.docker.io $scheme://$http_host;
  7. }
以上配置将客户端上传的数据限制在 1GB,如有特殊需求请自行修改。
访问此 location 对应的地址,如果得到的响应和访问 https://registry-1.docker.io 一模一样,就表示代理成功了。接下来,按照修改 Docker 配置章节设置 registry-mirrors 即可。
此方案简单有效,可用性也非常高。
本地代理
通过代理本地网络访问被屏蔽的服务是最为通用的方式,可以作为后备之选。
配置文件
Docker 自带一个配置后台进程 dockerd 的文件,它包含代理的配置选项。编辑 /etc/docker/daemon.json 文件,加入以下配置:
XML/HTML代码
  1. {
  2.   "proxies": {
  3.     "http-proxy": "http://proxy.example.com:8080",
  4.     "https-proxy": "https://proxy.example.com:8083",
  5.     "no-proxy": "*.test.example.com,.example.org,127.0.0.0/8"
  6.   }
  7. }
如果你是 Windows,路径在 C:\ProgramData\docker\config\daemon.json。
这里的 http-proxy 和 https-proxy 是你的代理软件的地址和端口,no-proxy 是不需要代理的地址列表。
如果你的 Docker 版本过低,有可能不支持这个配置。添加 Systemd 配置也可以设置 dockerd 的代理。创建 /etc/systemd/system/docker.service.d/http-proxy.conf 文件,写入以下环境变量:
XML/HTML代码
  1. [Service]
  2. Environment="HTTP_PROXY=http://proxy.example.com:8080"
让环境变量生效:
XML/HTML代码
  1. sudo systemctl daemon-reload
  2. sudo systemctl restart docker
现在你的 Docker 就可以通过代理访问 Docker Hub 了。当然,这还没完。本文虽然不会告知具体的代理搭建方法,但后文会提供一些思路。
构建代理
以上配置对于 pull 和 push 是有效的,但在本地构建镜像仍然会因为外部连接问题而受到影响。可以尝试使用 docker build 命令的 --build-arg 选项来在构建时使用代理:
XML/HTML代码
  1. docker build --build-arg http_proxy=http://proxy.example.com:8080
代理方案
你可以使用常见的代理工具如 Shadowsocks/V2Ray/Clash,并通过 gost 将 SOCKS5 代理转换为 HTTP 代理。假设 localhost:1080 是你的代理工具的 SOCKS5 地址,那么你可以这样启动 gost:
XML/HTML代码
  1. gost -L=http://:8080 -F=socks5://localhost:1080
配置成 gost 的地址后,Docker 访问 registry 的流量就会走代理了。
这是个人和公司内部都适用的方案。只要代理用的服务器网络路线好,速度和稳定性都很强。

« 上一篇 | 下一篇 »

发表评论

评论内容 (必填):