51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

自建Docker镜像代理加速

前言 {#前言}

本来想打算部署一个memos,结果本地用docker部署的时候发现压根拉不下来。最后网上查到被墙了,使用了国内大厂的源也是一样用不了,有些人说阿里可以用,实测不行

312856a3-6b11-45da-8ac7-e6c66fc7dac6

申请域名 {#申请域名}

namesilo 上随便申请一个结尾是 xyz 的域名,可以使用子域名的,可以多个地方使用。可以支付宝付款 大概10元左右,比如说下面这个

4eb0ce17-86fa-43ff-bff5-a9112b0ec87e

cloudflare托管域名 {#cloudflare托管域名}

登录 cloudflare 添加站点 直接输入刚刚申请的域名

18f86492-3f92-4893-866a-28e94ee69d61

到第3部的时候会有两个NS的服务器值

9704d602-43a7-48fe-b664-f46b1281dc71

回到 namesilo 点击右上角的头像的 My Account

8a41e033-06d2-4637-9fdf-88220fb93c95

再面板里面点击管理 Manage

6ab6284e-a6e2-42e1-95ab-903e99a7f40f

点进去之后就可以看到购买的域名列表 点击购买的域名

056627e5-cb44-4b2c-9b4a-2cb2d4cc70d5

点进去可以可以看到域名目前的NS,点击右边笔 把默认的全部删除 改成上面获取到的NS也就是上面的 iris.ns.cloudflare.commemphis.ns.cloudflare.com ,改完后就是下面图这样

7038282d-3053-4119-8326-33b4a464ae51

再回到 cloudflare 点击检查服务器即可,点击检查服务器之后需要等待,可以先做下面的步骤。成功之后就会收到邮件通知

ea475cea-89db-4209-9f29-c80d0b95118e

创建Workers {#创建Workers}

cloudflare 上点击左边的Workers 和 Pages

30d3e37b-a0e1-46e8-bc93-b38a3d65a4bf

在右边先点击创建 然后在点击创建worker

fb841094-7daa-41b6-851e-6049218e5643

起一个记得住的名字 点击保存

b9e9d173-11a8-44ac-acf8-f8e0b63ee03e

保存后到下面这里 直接点击完成

26ae987f-51c5-4490-8927-8d6dad68cd92

点击完成后就部署成功 需要修改代码 点击编辑代码

eb34fecf-51e2-4559-833d-2eebe949160f

删除默认的代码

6724f75c-c10f-4b74-af29-44bb44fc770e

把下面的代码粘贴到里面

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 'use strict' const hub_host = 'registry-1.docker.io' const auth_url = 'https://auth.docker.io' const workers_url = 'https://你的域名' //const home_page_url = '远程html链接' /** @type { RequestInit } */ 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' , }), } /** * @param { any } body * @param { number } status * @param { Object<string, string> } headers */ function makeRes ( body, status = 200 , headers = {} ) { headers[ 'access-control-allow-origin' ] = '*' return new Response (body, {status, headers}) } /** * @param { string } urlStr */ 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) }) /** * @param { FetchEvent } e */ async function fetchHandler ( e ) { const getReqHeader = ( key ) => e. request . headers . get (key); let url = new URL (e. request . url ); if (url. pathname === '/' ) { // Fetch and return the home page HTML content //return fetch(home_page_url); return new Response (indexHtml, { headers : { 'Content-Type' : 'text/html' } }); } 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) } 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; } /** * @param { Request } req * @param { string } pathname */ function httpHandler ( req, pathname ) { const reqHdrRaw = req. headers // preflight if (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 = pathname const urlObj = newUrl (urlStr) /** @type { RequestInit } */ const reqInit = { method : req. method , headers : reqHdrNew, redirect : 'follow' , body : req. body } return proxy (urlObj, reqInit, rawLen, 0 ) } /** * * @param { URL } urlObj * @param { RequestInit } reqInit */ async function proxy ( urlObj, reqInit, rawLen ) { const res = await fetch (urlObj. href , reqInit) const resHdrOld = res. headers const resHdrNew = new Headers (resHdrOld) // verify 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 }) } const indexHtml = ` <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>在Linux上设置Docker Hub Registry Mirror</title> <style> body { max-width: 800px; margin: 0 auto; padding: 20px; line-height: 1.6; color: #333; background-color: #f7f7f7; } h1 { color: #0066cc; margin-bottom: 30px; } h2 { color: #0066cc; margin-top: 40px; } pre { background-color: #fff; padding: 15px; padding-top: 48px; overflow-x: auto; border-radius: 8px; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1); } ol { margin-top: 20px; padding-left: 20px; } li { margin-bottom: 10px; } code { font-family: Consolas, monospace; background-color: #fff; padding: 2px 4px; border-radius: 3px; } .container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1); } .copy-btn { position: absolute; top: 10px; right: 10px; padding: 4px 10px; background-color: #0066cc; color: #fff; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; transition: background-color 0.3s; } .copy-btn:hover { background-color: #0052a3af; } .code-wrapper { position: relative; } </style> </head> <body> <div class="container"> <h1>在Linux上设置Docker Hub Registry Mirror</h1> <p>为了加速Docker镜像的下载速度,你可以设置Docker Hub的registry mirror</p> <h2>设置步骤</h2> <ol> <li>创建或编辑<code>/etc/docker/daemon.json</code>文件,添加以下内容:</li> </ol> <div class="code-wrapper"> <pre> echo '{"registry-mirrors": [" ${workers_url} "]}' | sudo tee /etc/docker/daemon.json > /dev/null</pre> <button class="copy-btn" onclick="copyCode(this)">复制</button> </div> <ol start="2"> <li>重启Docker服务:</li> </ol> <div class="code-wrapper"> <pre>sudo systemctl restart docker</pre> <button class="copy-btn" onclick="copyCode(this)">复制</button> </div> <p>设置完成后,Docker将会从您配置的registry mirror中拉取镜像,加速镜像下载过程。</p> </div> <script> function copyCode(btn) { const pre = btn.previousElementSibling; const code = pre.innerText; navigator.clipboard.writeText(code).then(function () { btn.innerText = '已复制'; setTimeout(function () { btn.innerText = '复制'; }, 2000); }, function () { alert('复制失败,请手动复制。'); }); } </script> </body> </html> ` |

修改代码 把 workers_url 改成刚刚申请的域名,比如申请的域名是 xb0.xyz 那么这里就写 https://xb0.xyz 当然也可以使用子域名 比如 https://docker.xb0.xyz

4fc53365-392b-492f-b744-9fa00c5bfb5d

最后点击右上角的部署即可

35ef1666-5762-4357-b66c-1e909befb3da

回到设置 点击触发器 添加自定义域

df7c0436-ff26-4283-a89f-4cc3cb677e4e

填写刚刚在代码文件里面写的域名 比如填的是 https://docker.xb0.xyz 那么这里就写 docker.xb0.xyz 填写完成点击添加自定义域。等待部署完成即可

26956331-39c6-4dbf-b344-bd981322db5a

修改Docker镜像源 {#修改Docker镜像源}

我用的不是直接的Docker桌面软件,而且更小的 orbStack 可能更改方式有点区别

打开OrbStack的设置 找到Docker 直接填写刚刚定义的域名即可 默认配置里面什么都没有 不需要刻意去格式化 点击Apply的时候会自动转义和格式化

|---------------------------------------------------------------| | { "registry-mirrors" : [ "https://docker.xb0.xyz" ] } |

806d4718-66f2-44db-a7c0-fb5a0a2fb222

验证 {#验证}

安装个memos查看是否成功

591d13ac-3267-4345-868c-d218459d1fb2

赞(2)
未经允许不得转载:工具盒子 » 自建Docker镜像代理加速