Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

2024-07-29 10:09:11 91点赞 1082收藏 83评论

大家好,我是羊刀仙。

Docker镜像拉取一直是个比较让人头疼的事情,尤其是不久之前那档子公告发布后,作为NAS用户真的太痛了~

本期内容为通过 Cloudflare Workers 搭建一个免费的Docker镜像加速服务。一个Cloudflare账户和一个域名即可搞定,按文章步骤来,部署使用轻松加愉快。

后面我也会再发一篇同样十分稳定的真付费方式,大家可以关注下。

Cloudflare Workers方案优势


  • CloudFlare拥有全球化的CDN网络,加速效果很不错;

  • Workers提供了免费的计算资源,几乎无成本;

  • 配置简单,全程配置仅需动手;

  • 安全可靠,不用担心镜像源跑路。

关于Cloudflare账户注册不赘述,像申请QQ账号一样简单。

Cloudflare接管DNS解析


这一步是必须的。

首先要转移域名DNS服务,让Cloudflare接管,相关操作可以看之前文章,也是十分简单~这里以腾讯云为例。

开始部署服务


返回进入Cloudflare主界面,左侧栏点击Workers 和 Pages,右侧点击创建Workers

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

命名后直接点击部署:

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

部署完毕后,点击编辑代码:

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

可以看到worker.js文件,将下面这一大串复制粘贴进去,第四行你的域名就是上面托管好的域名(建议二级域名),这里先不急着填写,点击右上角的部署:

如果代码有问题,可以移步我的BLOG查看,大妈可能吞格式,查起来太麻烦!

'use strict'; const hub_host = 'registry-1.docker.io'; const auth_url = 'https://auth.docker.io'; const workers_url = 'https://docker.ydxian.love'; 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 (!/%2F/.test(url.search) && /%3A/.test(url.toString())) { let modifiedUrl = url.toString().replace(/%3A(?=.*?&)/, '%3Alibrary%2F'); url = new URL(modifiedUrl); } 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.search; return fetch(new Request(token_url, e.request), token_parameter); } if (/^/v2/[^/]+/[^/]+/[^/]+$/.test(url.pathname) && !/^/v2/library/.test(url.pathname)) { url.pathname = url.pathname.replace(//v2//, '/v2/library/'); } 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 = await original_response_clone.text(); 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; if (req.method === 'OPTIONS' && reqHdrRaw.has('access-control-request-headers')) { return new Response(null, PREFLIGHT_INIT); } let rawLen = ''; const reqHdrNew = new Headers(reqHdrRaw); let urlStr = pathname; const urlObj = newUrl(urlStr); const reqInit = { method: req.method, headers: reqHdrNew, redirect: 'follow', body: req.body }; return proxy(urlObj, reqInit, rawLen); } async function proxy(urlObj, reqInit, rawLen) { const res = await fetch(urlObj.href, reqInit); const resHdrOld = res.headers; const resHdrNew = new Headers(resHdrOld); if (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.status; resHdrNew.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 }); } Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

接着返回上一界面,如图所示,选中设置,找到触发器,点击添加自定义域

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

可以用主域名,也可以用泛域名,看各位喜好了,我就用的二级域名。填写完后点击添加自定义域

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

完事儿后等域名证书发放(等几分钟手动刷新页面),显示不活动有效都证明成功,这时点击右上角的编辑代码

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

把整个二级域名填写进去,填写格式请严格按照下图格式来,填好了点击右上角部署

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

部署完后,就完全齐活儿啦。

实际测试


⭕️试试威联通NAS

熟悉的操作,打开Container Station,点击左侧存储-添加

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

如下图所示,添加存储库并测试,连通性通过的话点击应用

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

接着点击左侧栏映像-提取,测试一下实际提取如何。同样的需要我们选择刚添加的库,这里以数据库项目mysql测试,可以顺手把设置为默认勾选上

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

速度还是很不错的,cloudflare 牛哇!

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

通过Docker Compose部署也非常简单只需改动一个位置:

image: antonyleons/ward # 改为 image: docker.ydxian.love/antonyleons/ward

如下图所示,其他全部保持原样子,不过如果一个应用包含多个容器时,记得每个image都要改掉!

Docker镜像提取失败?10分钟快速解决,简单稳定好用!Cloudflare篇

最后


有需要的朋友可以按文章步骤搞起来自用,不建议公开公用。本文涉及的域名服务不久也将撤销,届时也会失效。

感谢观看,本文完。

展开 收起
83评论

  • 精彩
  • 最新
  • 现在到了“接着返回上一界面,如图所示,选中设置,找到触发器,点击添加自定义域:”这一步,返回后就显示“看来我们遇到了一些内部问题。我们的团队已收到通知。如果您希望提供帮助,请在下面告诉我们发生的情况。”,到不了显示触发器那个页面。
    不知是自己操作没做对,还是Cloudflare系统问题。

    校验提示文案

    提交
  • 科学出国,解决一切问题

    校验提示文案

    提交
    能科学的大哥必然不需要玩这个 [高兴]

    校验提示文案

    提交
    能科学也不会怎么下载 [尴尬]

    校验提示文案

    提交
    还有4条回复
    收起所有回复
  • 问题是连cf都抽风,怎么破。早晚被墙掉。

    校验提示文案

    提交
    通过VPS自建= =

    校验提示文案

    提交
    1h1g 80块一年,每月4tb完全够

    校验提示文案

    提交
    还有10条回复
    收起所有回复
  • 听说会被封?

    校验提示文案

    提交
    自己玩别公开,别刷太多流量

    校验提示文案

    提交
    好,回头搞个小号玩玩。 [高兴]

    校验提示文案

    提交
    收起所有回复
  • cf works政策写清楚了不能做代理

    校验提示文案

    提交
    能用先用,还有很多解决办法,后面我会慢慢更新 [得逞]

    校验提示文案

    提交
    收起所有回复
  • 跟着步骤做了,不行,404

    校验提示文案

    提交
    可能是大妈的代码格式被吃部署的时候报错 代码行上面有我的博客地址 去那里面复制 昨天还有群友刚部署完

    校验提示文案

    提交
    抱歉,我的问题,在群晖里面拉不了,进终端里面可以拉下来镜像了 [观察]

    校验提示文案

    提交
    还有2条回复
    收起所有回复
  • 好复杂,没看懂

    校验提示文案

    提交
    别怕,按着步骤来很轻松的 [doge]

    校验提示文案

    提交
    亲,两个问题:1.改完dns,我直接就外网登陆不了群晖了;
    2.复制完一屏幕的代码(你博客里复制的),提交系统直接说有错误。

    校验提示文案

    提交
    收起所有回复
  • 看到命令行,我就去咸鱼了

    校验提示文案

    提交
    去黄鱼市场,干啥?

    校验提示文案

    提交
    别闲鱼啊,只需你复制粘贴就行 [小怒]

    校验提示文案

    提交
    还有3条回复
    收起所有回复
  • SYNOLOGY 怎么设置? 大佬给看看。

    校验提示文案

    提交
    把域名添加进注册表

    校验提示文案

    提交
    收起所有回复
  • 速度还好

    校验提示文案

    提交
    已经算是很不错了,甚至比我用小鸡搭建的还要快

    校验提示文案

    提交
    收起所有回复
  • 我按照大佬教程一步一个脚印设置的,为啥我测试通了,但是就是下载不了

    校验提示文案

    提交
    威联通吗 捋一捋哪一步出问题了 我文章里的还没撤掉还能用

    校验提示文案

    提交
    我一样的问题,下载不下来

    校验提示文案

    提交
    还有3条回复
    收起所有回复
  • 没啥用,基本上拉两次机就拉不了了

    校验提示文案

    提交
    我文章里的那个到现在还没撤,不知道被多少人用了,公司NAS也在用我这个 [皱眉]

    校验提示文案

    提交
    我的不知道什么情况两天就废了

    校验提示文案

    提交
    收起所有回复
  • 掌握魔法才是硬道理 [高兴] 白嫖甲骨文流量根本用不完

    校验提示文案

    提交
    牛牛牛

    校验提示文案

    提交
    求细说说,哪怕只是关键字也行啊

    校验提示文案

    提交
    还有7条回复
    收起所有回复
  • blog进不去了

    校验提示文案

    提交
    修好了~让我玩炸了

    校验提示文案

    提交
    收起所有回复
  • 科学网络 省心, 没设备就在其他pc上抓取导出,离线安装

    校验提示文案

    提交
    有步骤吗 [高兴]

    校验提示文案

    提交
    收起所有回复
  • 老哥会操作,本地docker安装glider制作本地代理池吗。我操作半天没办法正常运行

    校验提示文案

    提交
  • 哎呀呀好像不行呀,Portainer拉不到镜像

    校验提示文案

    提交
  • 6月出的教程,我到8月了,还是没明白为什么我的自定义域名不能用…

    校验提示文案

    提交
  • 收藏,吃灰

    校验提示文案

    提交
  • 自定义域名的话需要怎么设置?

    校验提示文案

    提交
提示信息

取消
确认
评论举报

相关文章推荐

更多精彩文章
更多精彩文章
最新文章 热门文章
1.0K
扫一下,分享更方便,购买更轻松