利用cloudflare workers解决docker无法拉取镜像问题

news/2024/10/24 1:56:38/文章来源:https://www.cnblogs.com/guangdelw/p/18246236

由于某些原因,目前国内无法正常拉取docker镜像,很多以前的加速网站也都无法使用了

虽然阿里的个人专属镜像加速还能用,但是已经大不如以前了,很多时候都会报错超时,所以,需要另寻它途

而cloudflare workers则可以非常完美的解决这个需求

准备

  • 一个自己的域名

  • cloudflare账号

将域名托管到cloudflare上

我这边就不拿真实的域名举例了 就以 abc.com 举例

如果是在cloudflare上注册的域名,就不用这一步

点击:域注册--->转移域--->开始使用

输入自己的域名

计划 选择最下面的免费

然后选择开始扫描

开始激活,提示,需要更改名称服务器

需要将域名的权威服务器更改成给定的这两个权威服务器

我的域名是在腾讯云上,其他厂商也都类似

找到自己的域名,点击管理

点击修改DNS服务器

然后将cloudflare上给定的两个dns服务器设置到这里,然后提交

然后回到cloudflare,点击继续

然后提示正在等待激活

激活成功,会发邮件提示

然后在主页上就可以看到了

在转移域中也会显示不可转移了,这是因为这个域名已经转移了

到这里,域名托管就完成了

部署服务

登录到cloudflare后,进入 "Workers 和 Pages" 的 概述页面,点击 创建 Worker

设置自己的项目名称,这里以docker为例,然后点击下面的完成

然后点击 编辑代码

然后把以下代码复制到里面,并将自己的域名设置进去,再点击部署。

'use strict'
const hub_host = 'registry-1.docker.io'
const auth_url = 'https://auth.docker.io'
const workers_url = 'https://自己的域名'
const PREFLIGHT_INIT = {status: 204,headers: new Headers({'access-control-allow-origin': '*','access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS','access-control-max-age': '1728000',}),
}
function makeRes(body, status = 200, headers = {}) {headers['access-control-allow-origin'] = '*'return new Response(body, {status, headers})
}
function newUrl(urlStr) {try {return new URL(urlStr)} catch (err) {return null}
}
addEventListener('fetch', e => {const ret = fetchHandler(e).catch(err => makeRes('cfworker error:\n' + err.stack, 502))e.respondWith(ret)
})
async function fetchHandler(e) {const getReqHeader = (key) => e.request.headers.get(key);let url = new URL(e.request.url);if (url.pathname === '/token') {let token_parameter = {headers: {'Host': 'auth.docker.io','User-Agent': getReqHeader("User-Agent"),'Accept': getReqHeader("Accept"),'Accept-Language': getReqHeader("Accept-Language"),'Accept-Encoding': getReqHeader("Accept-Encoding"),'Connection': 'keep-alive','Cache-Control': 'max-age=0'}};let token_url = auth_url + url.pathname + url.searchreturn fetch(new Request(token_url, e.request), token_parameter)}url.hostname = hub_host;let parameter = {headers: {'Host': hub_host,'User-Agent': getReqHeader("User-Agent"),'Accept': getReqHeader("Accept"),'Accept-Language': getReqHeader("Accept-Language"),'Accept-Encoding': getReqHeader("Accept-Encoding"),'Connection': 'keep-alive','Cache-Control': 'max-age=0'},cacheTtl: 3600};if (e.request.headers.has("Authorization")) {parameter.headers.Authorization = getReqHeader("Authorization");}let original_response = await fetch(new Request(url, e.request), parameter)let original_response_clone = original_response.clone();let original_text = original_response_clone.body;let response_headers = original_response.headers;let new_response_headers = new Headers(response_headers);let status = original_response.status;if (new_response_headers.get("Www-Authenticate")) {let auth = new_response_headers.get("Www-Authenticate");let re = new RegExp(auth_url, 'g');new_response_headers.set("Www-Authenticate", response_headers.get("Www-Authenticate").replace(re, workers_url));}if (new_response_headers.get("Location")) {return httpHandler(e.request, new_response_headers.get("Location"))}let response = new Response(original_text, {status,headers: new_response_headers})return response;
}
function httpHandler(req, pathname) {const reqHdrRaw = req.headers// preflightif (req.method === 'OPTIONS' &&reqHdrRaw.has('access-control-request-headers')) {return new Response(null, PREFLIGHT_INIT)}let rawLen = ''const reqHdrNew = new Headers(reqHdrRaw)const refer = reqHdrNew.get('referer')let urlStr = pathnameconst urlObj = newUrl(urlStr)/** @type {RequestInit} */const reqInit = {method: req.method,headers: reqHdrNew,redirect: 'follow',body: req.body}return proxy(urlObj, reqInit, rawLen, 0)
}
async function proxy(urlObj, reqInit, rawLen) {const res = await fetch(urlObj.href, reqInit)const resHdrOld = res.headersconst resHdrNew = new Headers(resHdrOld)// verifyif (rawLen) {const newLen = resHdrOld.get('content-length') || ''const badLen = (rawLen !== newLen)if (badLen) {return makeRes(res.body, 400, {'--error': `bad len: ${newLen}, except: ${rawLen}`,'access-control-expose-headers': '--error',})}}const status = res.statusresHdrNew.set('access-control-expose-headers', '*')resHdrNew.set('access-control-allow-origin', '*')resHdrNew.set('Cache-Control', 'max-age=1500')resHdrNew.delete('content-security-policy')resHdrNew.delete('content-security-policy-report-only')resHdrNew.delete('clear-site-data')return new Response(res.body, {status,headers: resHdrNew})
}

最后点击保存并部署

绑定域名并配置路由

cloudflare workers默认使用的是自动分配的域名,目前是不可访问,所以还需要绑定自己的域名。

点击:"Workers 和 Pages"--->概述--->上面新建的workers(docker)

点击:设置--->触发器--->添加路由

路由处输入域名的子域名,我这里设置 docker.abc.com/*,然后区域选择主域名 abc.com,最后添加路由

然后禁用原来默认的路由

给子域名添加解析

添加一个对应子域名的解析,例如上面是用docker.abc.com,那这里就添加一个对应的ipv4解析记录;

解析地址随便填写,填8.8.8.8就可以,然后旁边的小云朵一定要启用。

点击:网站--->自己的主域名(abc.com)

点击:DNS--->记录--->添加记录

  • 类型设置A
  • 名称设置docker,要域上面worker中设置的子域名保持一致
  • 设置ipv4地址 8.8.8.8
  • 开启代理

最后保存

验证并拉取镜像

如果以上步骤都无误,就可以直接拉取docker镜像,但是需要对相应的拉取命令做更改。

直接拉取

原命令

docker pull mysql:latest

现在需要在前面加上自己的域名

docker pull docker.abc.com/library/mysql:latest

或者

docker pull grafana/promtail:latest

现在需要在前面加上自己的域名

docker pull docker.abc.com/grafana/promtail:latest

设置docker registry

如果不想每次都在镜像前面加上自己的域名

就可以设置docker registry

vim /etc/docker/daemon.json{"registry-mirrors": ["https://docker.abc.com",]
}

最后重启docker,就大功告成了

注意

  1. cloudflare workers 每日总计免费10w次请求额度,普通人是几乎不可能用完,但为防止滥用仍建议添加路由和规则限制他人使用。
  2. 这个本质上是利用cloudflare来进行流量中转,受限于cf的速度,如果自己所在地区cf不可用或者速度偏低,那就需要自己用服务器搭建对应的中转服务了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/724353.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多款可观测产品全面升级丨阿里云云原生 5 月产品月报

《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供数字化的路径与指南。云原生月度动态 云原生是企业数字创新的最短路径。 《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供…

序列化-serialVersionUID作用

Serializable接口 作用:标记一个类可以被序列化,如果没有实现该接口,则会抛出异常。 ObjectOutputStream中源码:实验:serialVersionUID 作用:表示一个序列换版本,控制序列化与反序列化。 实现Serializable接口后,如果不显式设置serialVersionUID,那么系统会根据类中内…

【运维技巧】海豚调度工作流实例卡在正在停止任务实例卡在正在运行怎么办?

在大数据调度系统中,,大家可能会碰到任务实例状态更新不及时的情况。 对于Apache DolphinScheduler用户来说,这可能意味着前端显示的任务状态与实际情况不一致,即使任务已经在后台停止运行,前端仍显示为“正在运行”。这种现象不仅影响监控和管理,还可能导致后续任务调度…

想做物联网卡系统 是因为不想忍

(点击图片 查看 首年进度条)无论是否成功我们将持续投入最低三年持续资源研发开发开源IoTOS-物联网卡 这个体系的软件功能;期初做物联网卡软件仅仅是上班混口饭吃随着公司与发展看到了痛点及真实用户需求有了自身的想法想来做一套已 为使用者 ‘盈利’ 为目的 的物联网卡软件…

用于NLP的Python:使用Keras的多标签文本LSTM神经网络分类|附代码数据

全文下载链接:http://tecdat.cn/?p=8640 在本文中,我们将看到如何开发具有多个输出的文本分类模型。我们开发一个文本分类模型,该模型可分析文本注释并预测与该注释关联的多个标签。多标签分类问题实际上是多个输出模型的子集。在本文结尾,您将能够对数据执行多标签文本分…

微服务架构qiankun集成react子应用

前一篇文章讲了qiankun集成vue子应用,这篇随笔讲集成react子应用。 1、创建react子应用 用react脚手架初始化一个react项目,至于项目的数据仓库store和路由、以及UI组件库这里就不做讲解,可以自己自行网上找资料配置。create-react-app my-react-app2、在src路径下创建publ…

MyBatis 的在使用上的注意事项及其辨析

1. MyBatis 的在使用上的注意事项及其辨析 @目录1. MyBatis 的在使用上的注意事项及其辨析2. 准备工作3. #{ } 与 ${ } 的区别和使用{}3.1 什么情况下必须使用 $3.1.1 拼接表名3.1.2 批量删除3.1.3 模糊查询3.1.3.1 使用 ${ }的方式3.1.3.2 使用 #{ } 的方式4. typeAliases 别名…

IBM服务器阵列卡损坏恢复案例

一台IBM服务器,型号是7944IBM的3550M3的服务器差不多有10年左右,有4块1TB的SAS硬盘,开机面板有报错,系统进不了,是一台金蝶K3的就是ERP的财务服务器资料相当重要,客户的需求是希望就是数据不丢的前提下,把系统启动起来,给它修复。好在实际检测了硬件后发现,是阵列卡损…

2轮DES差分分析

一、差分分析上图是2轮DES的框架图。是已知的,试图找出B和C的差分值:同样,为了计算方便,将L0等于L0*,那么,差分值就变成:二、代码实现 如果大家对代码实现感兴趣的话,可以根据2轮DES差分分析原理,对1轮差分分析代码做出调整,完成2轮差分分析代码实现。这里把2轮DES差…

pointer事件

需要同时处理PC端鼠标事件、移动端touch事件,用pointer事件吧! 参考:https://blog.csdn.net/qq_45472813/article/details/131484480

EXCEL不能访问.该文件可能是只读

大学教授的文档数据,分区误格式化,导致数据全部丢失。后来客户从网上下载免费数据恢复软件扫描,扫描出来以后大多打不开,提示:该文件可能是只读,不能访问,打开为乱码。客户将几个重要的文档发到我邮箱要求恢复。 打开文件,正如客户所描述,提示:不能访问“2009日报表.…

哪款工程项目管理系统最适合你?一文看懂顶级13款

本文将探讨12款顶尖的工程项目管理系统软件,帮助您选择适合自己团队和项目需求的最佳工具。国内外主流的13款工程项目管理系统软件:Worktile、中建软件、泛微建筑项目管理软件、LiquidPlanner、Wrike、建文软件、广联达、Microsoft Project、泛普软件、Procore、Buildertrend…