最近由于ZC的原因,国内的知名公开镜像源失效了,许多开发者在使用 Docker 镜像时常常面临一个问题:镜像拉取速度往往较慢,有些镜像无法拉取。目前整理出网络上的解决方式。每一个我都自己搭建过。如果需要,请结合选择。

一、阿里云代理

这个神奇的项目:tech-shrimp/docker_image_pusher。这是一个利用Github Action自动化将DockerHub镜像同步到阿里云容器镜像服务的解决方案。

1、配置阿里云docker镜像仓库

  • 登录阿里云容器镜像服务

首先我们需要登录到阿里云容器镜像服务 https://cr.console.aliyun.com/

image-20240704234258725

个人实例可以免费创建3个命名空间,300个镜像,对于我们个人来说已经足够了。

  • 创建命令空间

在个人实例下创建一个命名空间,我们需要记住此处创建的命令空间,后边会用到。

image-20240704234401838

  • 设置凭证

在访问凭证中设置固定密码,我们需要记住密码,以及此处的用户名和仓库地址,后边会用到。

image-20240704234839496

2、配置环境变量

点击 Settings -> Secret and variables -> Actions -> New Repository secret,依次将我们之前配置的阿里云容器镜像服务的值配置到此处:

  • ALIYUN_NAME_SPACE: 命名空间
  • ALIYUN_REGISTRY: 仓库地址
  • ALIYUN_REGISTRY_PASSWORD: 密码
  • ALIYUN_REGISTRY_USER:用户名

图片3、转存镜像

配置完成后修改项目的images.txt文件,将我们要转存的镜像添加上去,提交代码。

图片

提交之后会自动进入Github Action构建,如下图所示则为构建成功了

image-20240704235220291

4、查看镜像

转存成功后我们在阿里云容器镜像服务 https://cr.console.aliyun.com/中就可以看到我们转存的镜像了

image-20240704235251252

点击镜像名称就可以看到我们的镜像地址了:

image-20240704235341573

二、Cloudflare 代理

方式一:可以参考我前面的这篇博客。利用Cloudflare workers拉取dockerhub镜像

这里介绍的是方式二。包含多个镜像源的代理

前提

  • 有 Cloudflare 账号
  • (可选)有自定义的域名,且域名托管在 Cloudflare 上
  • Cloudflare Workers 额度足够

这里使用 Cloudflare Worker - cloudflare-docker-proxy 搭建。原文 README 步骤有一些问题,可以参考这篇 README.md 来实施。

这里以自定义域名配置方式举例, 步骤如下:

  1. 这里使用 Cloudflare Worker - cloudflare-docker-proxy 搭建。原文 README 步骤有一些问题,可以参考这篇 README.md 来实施。
  2. Deploy 按钮对应 URL 调整为您自己的 repo url
  3. 修改 src/index.jsconst routes 块的内容
1
2
3
4
5
6
7
const routes = {
"docker.your-domain.com": "https://registry-1.docker.io",
"quay.your-domain.com": "https://quay.io",
"gcr.your-domain.com": "https://k8s.gcr.io",
"k8s-gcr.your-domain.com": "https://k8s.gcr.io",
"ghcr.your-domain.com": "https://ghcr.io",
};

点击 “Deploy” 按钮部署,部署后如下:

image-20240704235950772

Cloudflare Worker

在 Cloudflare 的 DNS 记录里添加 CNAME 指向部署后的 ${workername}.${username}.workers.dev 地址。如下:

Cloudflare DNS Records

在 Workers 的 HTTP Routes 里,添加 xxx.your-domain.com/* 路由指向 cloudflare-docker-proxy, xxx 就是 docker quay gcr 等,如下:

Cloudflare Worker Routes

三、服务器搭建代理

前提:

  • 购买一台国外的云服务器并且没有被墙,用来搭建docker镜像仓库代理服务
  • 准备一个域名,然后到腾讯云或者阿里云上申请一个免费的证书;如果有多个代理的地址则要配置多个二级域名,然后购买一个通配符证书(说明:如果你使用cloudflare进行DNS解析,开启CF代理就不需要单独购买证书了,CF会免费提供https服务)
  • 安装Nginx,配置域名和证书,然后反代我们的Registry容器服务
  • 安装部署Docker和docker-compose

项目地址:https://github.com/dqzboy/Docker-Proxy

1、域名SSL

参考github作者描述的提前准备功能。

image-20240705000707061

2、Docker Compose 部署

下载config目录下对应的yml文件到你本地机器上。我的配置文件放在config目录下

image-20240705000823619

image-20240705000915568

下载docker-compose.yaml文件到你本地机器上。需要需要改映射目录。(根据自己实际情况来)

image-20240705001117533

image-20240705001155824

1
2
3
volumes:
- /opt/dockerHub/registry/data:/var/lib/registry
- /opt/dockerHub/config/registry-hub.yml:/etc/docker/registry/config.yml

执行 docker compose 命令启动容器服务

1
2
3
4
docker compose up -d

# 查看容器日志
docker logs -f [容器ID或名称]

3、Nginx 反向代理

前提需要安装好nginx。注意you.name.com 是你自己的域名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
server {
listen 5051 ssl;
server_name you.name.com;

ssl_certificate /etc/nginx/you.name.com.pem;
ssl_certificate_key /etc/nginx/you.name.com_key.pem;

proxy_buffering off;
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_ssl_server_name on;
proxy_ssl_session_reuse off;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location ^~ / {
if ($request_uri ~ ^/v2/([^/]+)/(manifests|blobs)/(.*)$) {
# 重写路径并添加 library/
rewrite ^/v2/(.*)$ /v2/library/$1 break;
}
proxy_pass http://127.0.0.1:51000;
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-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}

server {
listen 5052 ssl;
server_name you.name.com;

ssl_certificate /etc/nginx/you.name.com.pem;
ssl_certificate_key /etc/nginx/you.name.com_key.pem;

proxy_buffering off;
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_ssl_server_name on;
proxy_ssl_session_reuse off;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location ^~ / {
proxy_pass http://127.0.0.1:52000;
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-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}

server {
listen 5053 ssl;
server_name you.name.com;

ssl_certificate /etc/nginx/you.name.com.pem;
ssl_certificate_key /etc/nginx/you.name.com_key.pem;

proxy_buffering off;
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_ssl_server_name on;
proxy_ssl_session_reuse off;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location ^~ / {
proxy_pass http://127.0.0.1:53000;
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-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}

server {
listen 5050 ssl;
server_name you.name.com;

ssl_certificate /etc/nginx/you.name.com.pem;
ssl_certificate_key /etc/nginx/you.name.com_key.pem;

proxy_buffering off;
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_ssl_server_name on;
proxy_ssl_session_reuse off;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://localhost:50000;
}

}

image-20240705001856188

使用自建的 Registry 地址替换官方的 Registry 地址拉取镜像

1
2
3
4
5
6
7
8
9
# docker hub Registry
## 源:nginx:latest
## 替换
docker pull hub.you.name.com/library/nginx:latest

# Google Registry
## 源:gcr.io/google-containers/pause:3.1
## 替换:
docker pull gcr.you.name.com/google-containers/pause:3.1

四、Render搭建代理

1、注册Render账号

注册地址在这里: https://dashboard.render.com/register
注册没啥难度, 也不需要绑信用卡信息, 主打白嫖无负担.

2、创建 Web Service

注册成功后, 进入控制台, 右上角点击New , 选择创建Web Service

image-20240822144213404

接下来, 选择 Existing Image , 重点来了, 在 Image Url 一栏,填写: docker.io/tony413/dockerproxy:latest 要一字不差, 这里先感谢 tony413 提供镜像.点击右下角 Connect。如果镜像无法使用就去hub.docker.com 找一个能使用的

image-20240822144405359

补充说明, 如果填写镜像地址后, 出现红色报错字样, 大概是没有权限之类的. 可以在下面那个Credential (Optional)输入框创建docker的认证信息, 需要你的dockerhub用户名, 和你的dockerhub Access Token 或者密码.

再接下来的页面, 有两个选项比较重要:

  • Region 选 新加坡 (Singapore). 毕竟离咱们近点,速度快点.
  • Instance Type 选 Free ! 啥也不说了, 白嫖党必选.

image-20240822144644225

其他啥也不用填, 拉到最后, 点击 Deploy Web Service

image-20240822144716231

接下来就自动进入控制台, 可以看到docker部署的细节.

3、部署成功, 开始使用

等待部署完成后, 可以看到一个绿色live 的标签, 表示已经部署成功了.
接下来复制保留好Render免费提供给你免费的域名, 这个就是docker镜像加速域名了. 是的, 连域名都给你准备好了. 主打一个省心.
分配给我的域名为: https://dp-imoyt.onrender.com/ 大家可以随意使用.

image-20240822145309509

4、使用方法

把这个镜像域名填写在你要拉取的镜像地址前作为前缀即可. 对于dockerhub的镜像需要补全 docker.io/ 例如 :

拉取 stilleshan/frpc:latest 镜像 可以写成:

  • docker pull dockerproxy-latest-pztf.onrender.com/docker.io/stilleshan/frpc:latest

同样, 使用 docker-compose 时 :

  • image: dockerproxy-latest-pztf.onrender.com/docker.io/stilleshan/frpc:latest

好了, 可以愉快的拉取镜像了.

5、注意事项, 关于免费服务器的限制.

  • Render 提供的免费实例, 每个月有750小时的免费开机时长, 超过了会自动停机. 每个月会自动重置.
  • 实例关机时, 是不消耗免费时长的.
  • 对于免费实例, 如果超过15分钟没有针对实例的web请求, 实例会自动进行停机休眠, 不消耗免费时长.
  • 对于已经休眠停机的实例, 如果有web请求, 会自动唤醒, 并且开始对外提供服务, 直到下次休眠.
  • 所以, 这个用来做个人的docker镜像代理, 还是比较匹配的. 毕竟拉取镜像的操作不是每天都进行. 如果实例休眠了, 多请求几次唤醒实例后, 就可以正常拉取. 对我来说也不是特别不能接受把.
  • 快速判断镜像地址是否可用, 可以直接在浏览器中访问你的分配域名, 比如 , 如果页面重定向到github, 那就说明此时可以正常拉取了
  • 建议使用 D监控 或 自己使用Docker搭建Uptime Kuma在线监控

6、补充说明

有的朋友提供了一些信息, 比如需要绑卡 或者 区域没有新加坡等等.

关于绑卡: 我又测试了几次, 更换了不同的ip, 注册虽然没问题, 但是部署服务的时候确实会弹出绑卡弹窗. 感觉应该是官方就在刚刚加了这一层认证, 估计是被薅怕了. 大家自行斟酌把, 看看要不要填写. 如果有虚拟信用卡到也无妨.

至于区域没有新加坡: 我确实没有复现这种情况, 至少在日本 美国 新加坡 韩国 等节点, 我测试都是有新加坡可以选择的, 如果有人遇到了区域没有新加坡, 可以留言提供一下ip.

image-20240822150132080

五、补充

docker修改配置代理

在docker的daemon.json配置文件中添加上docker.io的代理域名,然后重启docker程序

1
2
3
4
5
6
7
8
9
10
11
[root@BJ-Cloud ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://hub.your_domain_name"],
"log-opts": {
"max-size": "100m",
"max-file": "5"
}
}

#重启docker
systemctl restart docker

kubeadm配置镜像代理

如果你用 kubeadm 部署 Kubernetes 集群,可以在 kubeadm 配置文件中设置镜像地址为你的搭建的代理仓库的域名地址

1
2
3
4
5
6
7
~]# cat kubeadm-config.yaml

apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.25.1
......
imageRepository: gcr.your_domain_name/google-containers