公众号关注 「奇妙的 Linux 世界」
设为「星标」,每天带你玩转 Linux !
很早很早以前,我们都使用裸机部署应用,部署应用无非以下几步:
安装操作系统
安装运行环境(PHP,NodeJS,Ruby, etc)
安装/复制程序
尝试运行程序
报错,修环境问题
继续报错,修开发人员
开发人员提交一个很脏的 Hack,应用终于跑起来了
直到容器化的出现,开发和运维开发将整个程序和运行环境放在一个个 Docker Image 和 docker-compose.yml
中,启动一个程序已经慢慢缩减成了一行 docker run
或者 docker-compose up -d
,绿色无害,迁移方便,使用起来让人上瘾,想不断地使用 Docker,并不断将 Docker 融入自己的 Workflow 中,然而,Docker 用的多了,就会看到以下情况:
Error response from daemon: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit
打开这个页面,你就会知道,从 2020-11-02 开始,官方的 Docker Hub 开始对 pull 请求加上了限制,限制为匿名用户(未登录),每 6 小时只能拉 100 次 image,登录的免费用户每 6 小时拉 200 次 镜像:
The rate limits of 100 container image requests per six hours for anonymous usage, and 200 container image requests per six hours for free Docker accounts are now in effect.
对于登录而言,限制的是用户,对于未登录的用户而言,限制的是 IP。
Docker 要钱我可以理解, 但是 docker hub 上面 ubuntu:latest 这样的基础镜像都给我整一个 rate-limit 我是真的没想到。不知道今天起有多少人的 CI/CD 会因为这个挂掉。
——https://twitter.com/IceCode8964XI/status/1328395263606628352
这怎么行?
由于限制的是 pull 请求,为了摆脱这种限制,我们首先得了解 docker pull
背后到底做了啥,然后推测限制的位置并绕过。
我们虽然日常访问的是 https://hub.docker.com
,但是我们在 https://github.com/docker/distribution/blob/master/reference/normalize.go#L13 中可以看到实际 docker
使用的地址是一个硬编码的 docker.io
var (
legacyDefaultDomain = "index.docker.io"
defaultDomain = "docker.io"
officialRepoName = "library"
defaultTag = "latest"
)
在 Docker 的 API 文档:https://docs.docker.com/registry/spec/api/#pulling-an-image 中,我们知道:
An “image” is a combination of a JSON manifest and individual layer files. The process of pulling an image centers around retrieving these two components.
一个 docker pull
指令会拉两部分,一部分是 manifest,一部分是 layer,前者指定了一个 image 相关的信息和 layer 的信息(一个 JSON 文件),后者就是一些大文件(layer),从我们内部统计的情况来看,后者普遍使用的是 https://production.cloudflare.docker.com/
,这部分应该是不会受到限制的,所以猜测限制的地方是前者 manifest 的部分的请求,从文档 https://docs.docker.com/docker-hub/download-rate-limit/ 中我们也可以知道:
A pull request is defined as up to two GET requests on registry manifest URLs (/v2//manifests/).
故而证实了我们猜测,Docker Hub 是在拉 manifest 的过程中进行限制的。
那么 manifest 是从哪儿拉的?
由于没有地方记录了 docker pull
的时候到底是从哪儿拉的地址,需要 MITM 一下:
Flows
GET https://registry-1.docker.io/v2/
← 401 application/json 87b 213ms
GET https://auth.docker.io/token?account=youraccount&scope=repository%3Alibrary%2Fal
pine%3Apull&service=registry.docker.io
← 200 application/json 4.18k 245ms
>> GET https://registry-1.docker.io/v2/library/alpine/manifests/latest
← 200 application/vnd.docker.distribution.manifest.list.v2+json 1.6k 294ms
GET https://registry-1.docker.io/v2/library/alpine/manifests/sha256:57334c50959f26ce
1ee025d08f136c2292c128f84e7b229d1b0da5dac89e9866
← 200 application/vnd.docker.distribution.manifest.v2+json 528b 326ms
GET https://registry-1.docker.io/v2/library/alpine/blobs/sha256:b7b28af77ffec6054d13
378df4fdf02725830086c7444d9c278af25312aa39b9
← 307 text/html 242b 288ms
GET https://registry-1.docker.io/v2/library/alpine/blobs/sha256:0503825856099e6adb39
c8297af09547f69684b7016b7f3680ed801aa310baaa
← 307 text/html 242b 322ms
GET https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sh
a256/b7/b7b28af77ffec6054d13378df4fdf02725830086c7444d9c278af25312aa39b9/data?…
← 200 application/octet-stream 1.48k 191ms
GET https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sh
a256/05/0503825856099e6adb39c8297af09547f69684b7016b7f3680ed801aa310baaa/data?…
← 200 application/octet-stream 2.66m 207ms
⇩ [27/32] [*:8080]
我们会发现 https://registry-1.docker.io/v2/
这个地址,通过手动改 Host + 调路由的方式并重新 pull 发现可以成功之后得到了验证。
接下来就是给这个地址设置用不同的 IP 来请求这个地址即可绕开限制,比如..用 Tor。
刷 Docker Hub 流量固然很快乐,但是我们的主要目的还是保护内部 CI 不挂,且提升 pull 的速度,所以这个时候配置一个 pull-through cache[1] 才是一个比较合理的解决方式,嗷对了,如果你和我一样使用了自己的 cache 的话,记得改外部 DNS 设置,而不是容器内的 /etc/hosts
,不然容器内的程序还是会通过 Host 的 DNS 去查询 registry-1.docker.io
的 IP 并直连,让你继续看到 toomanyrequests。
[1]
配置一个 pull-through cache: https://github.com/n0vad3v/dockerfiles/tree/master/registry-pull-through-cache
本文转载自:「云原生实验室」,原文:https://tinyurl.com/yyywx6mq,版权归原作者所有。欢迎投稿,投稿邮箱: [email protected]。
你可能还喜欢
点击下方图片即可阅读
如何在 Docker 中使用 Docker
点击上方图片,打开小程序,加入「玩转 Linux」圈子
更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!