使用Caddy加速所有Docker仓库(包括gcr

引用一下这里的开头,这也是现在的真实感受。Envoy配置略显复杂不利于自行搭建推广,这里我们讨论下如何使用Caddy的反向代理来加速DockerQuayGCR,当然方法是通用的不止限于这些站点

在使用DockerKubernetes时,我们经常需要访问gcr.ioquay.io镜像仓库,由于众所周知的原因,这些镜像仓库在中国都无法访问,唯一能访问的是 docker.com,但速度也是奇慢无比
gcr.azk8s.cngcr.io镜像仓库的代理站点,但是目前*.azk8s.cn已经仅限于Azure中国的IP使用,不再对外提供服务了。国内其他的镜像加速方案大多都是采用定时同步的方式来缓存,不能保证及时更新,中科大和七牛云等镜像加速器我都试过了,非常不靠谱,很多镜像都没有

必要条件

一台可以施展魔法的主机是必须的,Caddy的安装也不在这篇教程里,最好使用泛域名解析,把*解析到这台主机

最好明白反向代理是什么,如果不是很清楚也不影响使用,只要知道流量是全走这台主机就行。如果传输过慢可以开启BBR加速,效果很好

下面以back.pub为例,但是并不是说这个域名有反向代理哦,如要使用请自行搭建。文章最后有一键配置

Docker简单反向代理

docker.com是最简单的,只需要配置下反向代理

1
2
3
4
5
6
7
8
9
10
11
hub.docker.back.pub {
encode gzip
reverse_proxy * https://registry-1.docker.io {
header_up Host registry-1.docker.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie registry-1.docker.io docker.back.pub
}
}

测试可用

docker pull hub.docker.back.pub/library/nginx

但是不是有时候感觉有点卡,甚至还是会和docker.io连接失败?下面会解答的,为什么还需要连接docker.io

GCR为什么不能用

上面方法也可以用于quay.io,但是反向代理gcr.io时会被hang住,那么就加上日志排查下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hub.gcr.back.pub {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://gcr.io {
header_up Host gcr.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie k8s.gcr.io gcr.back.pub
}
}

通过对日志的排查,我们发现是由于pull时要先去获取一个token,而gcr.io被完全屏蔽了,无法拿到token也就无法继续进行下载了

这个token获取和使用哪一个仓库没有关系,所以docker.comquay.io其实也有这一步,只不过他们虽然慢但还能访问而获取token并不会消耗多少流量,所以不明显罢了

知道问题之后就好解决了,利用Caddyheader_down来修改返回HeaderWww-Authenticate,添加如下配置

1
2
3
4
5
6
7
hub.gcr.back.pub {
...
reverse_proxy * https://gcr.io {
...
header_down Www-Authenticate "Bearer realm=\"https://hub.gcr.back.pub/v2/token\",service=\"gcr.io\""
}
}

经测试可行

docker pull hub.gcr.back.pub/google-containers/pause

K8S为什么不能用

但是现在仍然有一个问题,k8s.gcr.io有时候仍然不能使用,继续排查日志发现有Location跳转,修改即可

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
hub.k8s.back.pub {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://k8s.gcr.io {
header_up Host k8s.gcr.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie k8s.gcr.io gcr.back.pub
header_down Www-Authenticate "Bearer realm=\"https://hub.k8s.back.pub/v2/token\",service=\"k8s.gcr.io\""
header_down Location "https://storage.googleapis.com" "https://storage.googleapis.back.pub"
}
}

storage.googleapis.back.pub {
encode gzip
reverse_proxy * https://storage.googleapis.com {
header_up Host storage.googleapis.com
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie storage.googleapis.com storage.googleapis.back.pub
}
}

Docker继续完善

上面我们可以知道仅仅针对registry-1.docker.io配置反向代理是不够的,最好加上token和可能会出现的其它跳转

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
hub.docker.back.pub {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://registry-1.docker.io {
header_up Host registry-1.docker.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie registry-1.docker.io docker.back.pub
header_down Www-Authenticate "Bearer realm=\"https://auth.docker.back.pub/token\",service=\"registry.docker.io\""
header_down Location "https://production.cloudflare.docker.com" "https://production.cloudflare.docker.back.pub"
}
}

auth.docker.back.pub {
encode gzip
reverse_proxy * https://auth.docker.io {
header_up Host auth.docker.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie auth.docker.io docker.back.pub
}
}

production.cloudflare.docker.back.pub {
encode gzip
reverse_proxy * https://production.cloudflare.docker.com {
header_up Host production.cloudflare.docker.com
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie production.cloudflare.docker.com docker.back.pub
}
}

完整的配置文件

其它的站点的配置类似,下面给出一个完整的配置

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
116
117
118
119
120
121
122
123
124
125
126
127
128
# 请修改这个变量为你自己的域名
DOMAIN="back.pub"

cat << EOF > /etc/caddy/Caddyfile
hub.docker.${DOMAIN} {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://registry-1.docker.io {
header_up Host registry-1.docker.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie registry-1.docker.io docker.${DOMAIN}
header_down Www-Authenticate "Bearer realm=\"https://auth.docker.${DOMAIN}/token\",service=\"registry.docker.io\""
header_down Location "https://production.cloudflare.docker.com" "https://production.cloudflare.docker.${DOMAIN}"
}
}

auth.docker.${DOMAIN} {
encode gzip
reverse_proxy * https://auth.docker.io {
header_up Host auth.docker.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie auth.docker.io docker.${DOMAIN}
}
}

production.cloudflare.docker.${DOMAIN} {
encode gzip
reverse_proxy * https://production.cloudflare.docker.com {
header_up Host production.cloudflare.docker.com
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie production.cloudflare.docker.com docker.${DOMAIN}
}
}

hub.quay.${DOMAIN} {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://quay.io {
header_up Host quay.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie quay.io quay.${DOMAIN}
header_down Www-Authenticate "Bearer realm=\"https://hub.quay.${DOMAIN}/v2/auth\",service=\"quay.io\""
}
}

hub.gcr.${DOMAIN} {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://gcr.io {
header_up Host gcr.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie k8s.gcr.io gcr.${DOMAIN}
header_down Www-Authenticate "Bearer realm=\"https://hub.gcr.${DOMAIN}/v2/token\",service=\"gcr.io\""
}
}

hub.k8s.${DOMAIN} {
encode gzip
log {
level debug
output file /var/log/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
reverse_proxy * https://k8s.gcr.io {
header_up Host k8s.gcr.io
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie k8s.gcr.io gcr.${DOMAIN}
header_down Www-Authenticate "Bearer realm=\"https://hub.k8s.${DOMAIN}/v2/token\",service=\"k8s.gcr.io\""
header_down Location "https://storage.googleapis.com" "https://storage.googleapis.${DOMAIN}"
}
}

storage.googleapis.${DOMAIN} {
encode gzip
reverse_proxy * https://storage.googleapis.com {
header_up Host storage.googleapis.com
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Port {http.request.port}
header_up X-Forwarded-Proto {http.request.scheme}
header_down Set-Cookie storage.googleapis.com storage.googleapis.${DOMAIN}
}
}
EOF

systemctl restart caddy

使用Caddy加速所有Docker仓库(包括gcr
https://back.pub/post/docker-mirror-by-caddy/
作者
Dash
发布于
2020年8月30日
许可协议