来源: https://github.com/motao123/built-docker

Nginx 搭建

编辑 Nginx 配置,在 http 块下增加一个 server 块

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
#反代docker hub镜像源
server {
listen 443 ssl;
server_name 域名;

ssl_certificate 证书地址;
ssl_certificate_key 密钥地址;

ssl_session_timeout 24h;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

location / {
proxy_pass https://registry-1.docker.io; # Docker Hub 的官方镜像仓库
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;
# error_page 指令默认只检查了第一次后端返回的状态码,开启后可以跟随多次重定向。
recursive_error_pages on;
# 根据状态码执行对应操作,以下为301302307状态码都会触发
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;
}
}

CloudFlare Worker 搭建

在面板左侧找到 Workers 和 Pages,然后点击右侧的 创建应用程序、创建 Worker,修改一个好记的名字,部署

接下来编辑代码,将 worker.js 的内容替换为下面内容

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
import HTML from './docker.html';

export default {
async fetch(request) {
const url = new URL(request.url);
const path = url.pathname;
const originalHost = request.headers.get("host");
const registryHost = "registry-1.docker.io";

if (path.startsWith("/v2/")) {
const headers = new Headers(request.headers);
headers.set("host", registryHost);

const registryUrl = `https://${registryHost}${path}`;
const registryRequest = new Request(registryUrl, {
method: request.method,
headers: headers,
body: request.body,
// redirect: "manual",
redirect: "follow",
});

const registryResponse = await fetch(registryRequest);

console.log(registryResponse.status);

const responseHeaders = new Headers(registryResponse.headers);
responseHeaders.set("access-control-allow-origin", originalHost);
responseHeaders.set("access-control-allow-headers", "Authorization");
return new Response(registryResponse.body, {
status: registryResponse.status,
statusText: registryResponse.statusText,
headers: responseHeaders,
});
} else {
return new Response(HTML.replace(/{{host}}/g, originalHost), {
status: 200,
headers: {
"content-type": "text/html"
}
});
}
}
}

这里相比原项目,将 redirect: “manual” 修改为了 redirect: “follow”,目的是为了让脚本自行处理 307 跳转,直接返回给我们跳转后的数据。 新建一个名为 docker.html 的 文件,内容如下

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Mirror Usage</title>
<style>
html {
height: 100%;
}
body {
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
font-size: 16px;
color: #333;
margin: 0;
padding: 0;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;

}
.container {
margin: 0 auto;
max-width: 600px;
}

.header {
background-color: #438cf8;
color: white;
padding: 10px;
display: flex;
align-items: center;
}

h1 {
font-size: 24px;
margin: 0;
padding: 0;
}

.content {
padding: 32px;
}

.footer {
background-color: #f2f2f2;
padding: 10px;
text-align: center;
font-size: 14px;
}
</style>
</head>
<body>
<div class="header">
<h1>Mirror Usage</h1>
</div>
<div class="container">
<div class="content">
<p>镜像加速说明</p>
<p>
为了加速镜像拉取,你可以使用以下命令设置registery mirror:
</p>
<pre>
sudo tee /etc/docker/daemon.json &lt;&lt;EOF
{
"registry-mirrors": ["https://{{host}}"]
}
EOF
</pre>
</br>
<p>
为了避免 Worker 用量耗尽,你可以手动 pull 镜像然后 re-tag 之后 push 至本地镜像仓库:
</p>
<pre>
docker pull {{host}}/library/alpine:latest # 拉取 library 镜像
docker pull {{host}}/coredns/coredns:latest # 拉取 library 镜像
</pre>
</div>
</div>
<div class="footer">
<p>Powered by Cloudflare Workers</p>
</div>
</body>
</html>

接下来,点击右上角的 部署,稍等片刻

最后,返回面板,在 设置,触发器 处设置一个自己的域名,一切就大功告成了 不建议使用自带的 workers.dev 的域名,被墙了

Nginx 和 CloudFlare Worker 整合部署

利用服务器搭建的 Nginx 作为中转,优先由服务器直连 Docker hub 的官方源,当服务器的 IP 请求次数超限后(会报 429 错误),就把请求转发到 CloudFlare Worker 部署的镜像源上,利用 CloudFlare Worker 再做一次中转。这样就即保证了使用服务器中转提高速度,又保证了不会因为服务器的 IP 请求速度过多而受限制,唯一的限制就是服务器的带宽和流量了

将上面部署的 Nginx 配置替换为下面的配置并重新加载即可

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
#反代docker hub镜像源
server {
listen 443 ssl;
server_name 域名;

ssl_certificate 证书地址;
ssl_certificate_key 密钥地址;

proxy_ssl_server_name on; # 启用SNI

ssl_session_timeout 24h;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

location / {
proxy_pass https://registry-1.docker.io; # Docker Hub 的官方镜像仓库

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;
# error_page 指令默认只检查了第一次后端返回的状态码,开启后可以跟随多次重定向。
recursive_error_pages on;
# 根据状态码执行对应操作,以下为301302307状态码都会触发
#error_page 301 302 307 = @handle_redirect;

error_page 429 = @handle_too_many_requests;
}
#处理重定向
location @handle_redirect {
resolver 1.1.1.1;
set $saved_redirect_location '$upstream_http_location';
proxy_pass $saved_redirect_location;
}
# 处理429错误
location @handle_too_many_requests {
proxy_set_header Host 替换为在CloudFlare Worker设置的域名; # 替换为另一个服务器的地址
proxy_pass http://替换为在CloudFlare Worker设置的域名;
proxy_set_header Host $http_host;
}
}

如果想要反代 ghcr 镜像源呢?只要参考上面的配置,将域名、header 修改一下即可 并且因为 ghcr 好像不像 docker hub 有下载频率的限制,所以也不用去 Cloudflare Worker 部署了,直接在服务器上部署一个就行。

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
#反代ghcr镜像源
server {
listen 443 ssl;
server_name 域名;

ssl_certificate 证书地址;
ssl_certificate_key 密钥地址;
proxy_ssl_server_name on;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
#error_log /home/ubuntuago/proxy_docker.log debug;
if ($blocked_agent) {
return 403;
}

location / {
proxy_pass https://ghcr.io; # Docker Hub 的官方镜像仓库

proxy_set_header Host ghcr.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;
# error_page 指令默认只检查了第一次后端返回的状态码,开启后可以跟随多次重定向。
recursive_error_pages on;
# 根据状态码执行对应操作,以下为301302307状态码都会触发
error_page 301 302 307 = @handle_redirect;

#error_page 429 = @handle_too_many_requests;

}
#处理重定向
location @handle_redirect {
resolver 1.1.1.1;
set $saved_redirect_location '$upstream_http_location';
proxy_pass $saved_redirect_location;
}

}