← 返回 TimeAmber set 限制解除

【保姆级免费攻略】Docker 镜像提取失败解决方案

生活爱好者 资深生活爱好者 2024年10月08日 16:13


 本期文章通过Cloudflare Workers搭建一个免费的Docker镜像加速。跟着本文步骤操作,小白也可以部署成功。


搭建准备:一个域名+一个Cloudflare账户。Cloudflare账户注册很简单,搜索Cloudflare即可注册,本文的域名是在腾讯云购买。


一、域名注册

二、域名托管至Cloudflare

三、在Cloudflare部署服务

四、Container 部署




一、域名注册



登录腾讯云进行注册。



图片


根据自己的预算和需求选择想要的域名,点击添加购物车,然后进行购买。


图片


购买之前需要进行实名认证,官方给的消息是1~N个工作日,我大概三十分钟实名认证成功,认证成功后,接着去购买自己想要的域名。


图片



购买成功后,这里还需要对域名进行审核,同业也是说需要N个工作日后能审核成功,差不多一个小时后就审核通过,服务状态这里就显示正常。



图片



登录腾讯云DNSPOD


https://www.dnspod.cn/login?login_jump=yes&s_url=https%3A%2F%2Fconsole.dnspod.cn%2Fdns%2Flist&sync_code=1


图片


登录后,点击头像,接着点击API密钥。


图片


然后新建API密钥。注意:API密钥是构建腾讯云APIA请求的重要凭证,不要外泄,要妥善保存。


图片


创建Token:新建完密钥后,转到DNSPod Token


图片


输入密钥名称,方便管理。


图片


创建完密钥后,后跳出以下弹窗,DNSPod 不会存储原始密钥,将以上的信息只出现一次,可以保存在笔记本中。


图片





二、域名托管至Cloudflare




登入Cloudflare 后,点击添加站点。


图片


输入上面在腾讯云申请的域名。


图片


接着往下拉选择免费的。


图片


接着下来可以看到Cloudflare 分配的两个服务器名称,需要返回到腾讯云,添加分配的这两个 Cloudflare 名称服务器,删除任何其他名称服务器,然后保存更改。


图片


返回到腾讯云,修改DNS服务器。


图片


点击自定义DNS,将上面分配的两个 Cloudflare 名称服务器复制到这里。


图片

回到Cloudflare ,左上角显示已激活,右下方的基本功能进行启用。


图片





三、在Cloudflare部署服务



进入Cloudflare主页面,按照下图依次点击Workers和Pages→创建Workers。


图片



登录前需要进行邮箱验证。


图片


下图位置输入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 (!/%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+申请的域名。


图片


接着等待域名证书发放,几分钟就可以成功,在等待期间去点击右上角【编辑代码】。


图片


把如下位置,填上自己的域名,按照下图格式填写。


图片


部署完就结束了。




四、Container 部署



回到威联通NAS进入 Container Station,进入存储库→添加。


图片


按照下图填写,测试连接不要忘记点。


图片


接着在【映像】中点击提取,同样按照下图操作,最后提取。


图片


这样就部署成功了,接下来进行测试,提取之前一个游戏的映像名称。


图片


可以成功提取。


图片

玩转NAS · 目录
上一篇旅游好助手--NAS,关键时刻帮你省下买iphone的钱下一篇用NAS搭建属于自己的私密树洞-WordPress

微信扫一扫
关注该公众号