ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【docker】设置镜像源 [打印本页]

作者: 星球的眼睛    时间: 2025-1-20 23:39
标题: 【docker】设置镜像源
1.创建workers,把下面代码粘贴到workers.js里部署就行了,还要自界说域。

2.修改一下docker的设置文件,修改文件 /etc/docker/daemon.json,把域名加入进去。
不设置镜像源地点的话,在docker pull的时候,在镜像前面加你的镜像站域名(二选一吧,不外设置文件一劳永逸...
  1. /etc/docker/daemon.json                                                      
  2. {
  3.     "registry-mirrors" : [
  4.     "你的域名"
  5.   ]
  6. }
复制代码
最后,固然cloudflare在国内也挺慢的,勉强能用。直接去白嫖个人的镜像站也挺好的。嘻嘻,这就要你去网上找找啦。
   下面是workers.js
  1. // _worker.js
  2. // Docker镜像仓库主机地址
  3. let hub_host = 'registry-1.docker.io'
  4. // Docker认证服务器地址
  5. const auth_url = 'https://auth.docker.io'
  6. // 自定义的工作服务器地址
  7. let workers_url = 'https://你的自定义的workers域名'
  8. // 根据主机名选择对应的上游地址
  9. function routeByHosts(host) {
  10.                 // 定义路由表
  11.         const routes = {
  12.                 // 生产环境
  13.                 "quay": "quay.io",
  14.                 "gcr": "gcr.io",
  15.                 "k8s-gcr": "k8s.gcr.io",
  16.                 "k8s": "registry.k8s.io",
  17.                 "ghcr": "ghcr.io",
  18.                 "cloudsmith": "docker.cloudsmith.io",
  19.                
  20.                 // 测试环境
  21.                 "test": "registry-1.docker.io",
  22.         };
  23.         if (host in routes) return [ routes[host], false ];
  24.         else return [ hub_host, true ];
  25. }
  26. /** @type {RequestInit} */
  27. const PREFLIGHT_INIT = {
  28.         // 预检请求配置
  29.         headers: new Headers({
  30.                 'access-control-allow-origin': '*', // 允许所有来源
  31.                 'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS', // 允许的HTTP方法
  32.                 'access-control-max-age': '1728000', // 预检请求的缓存时间
  33.         }),
  34. }
  35. /**
  36. * 构造响应
  37. * @param {any} body 响应体
  38. * @param {number} status 响应状态码
  39. * @param {Object<string, string>} headers 响应头
  40. */
  41. function makeRes(body, status = 200, headers = {}) {
  42.         headers['access-control-allow-origin'] = '*' // 允许所有来源
  43.         return new Response(body, { status, headers }) // 返回新构造的响应
  44. }
  45. /**
  46. * 构造新的URL对象
  47. * @param {string} urlStr URL字符串
  48. */
  49. function newUrl(urlStr) {
  50.         try {
  51.                 return new URL(urlStr) // 尝试构造新的URL对象
  52.         } catch (err) {
  53.                 return null // 构造失败返回null
  54.         }
  55. }
  56. function isUUID(uuid) {
  57.         // 定义一个正则表达式来匹配 UUID 格式
  58.         const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
  59.        
  60.         // 使用正则表达式测试 UUID 字符串
  61.         return uuidRegex.test(uuid);
  62. }
  63. async function nginx() {
  64.         const text = `
  65.         <!DOCTYPE html>
  66.         <html>
  67.         <head>
  68.         <title>Welcome to nginx!</title>
  69.         <style>
  70.                 body {
  71.                         width: 35em;
  72.                         margin: 0 auto;
  73.                         font-family: Tahoma, Verdana, Arial, sans-serif;
  74.                 }
  75.         </style>
  76.         </head>
  77.         <body>
  78.         <h1>Welcome to nginx!</h1>
  79.         <p>If you see this page, the nginx web server is successfully installed and
  80.         working. Further configuration is required.</p>
  81.        
  82.         <p>For online documentation and support please refer to
  83.         <a href="http://nginx.org/">nginx.org</a>.<br/>
  84.         Commercial support is available at
  85.         <a href="http://nginx.com/">nginx.com</a>.</p>
  86.        
  87.         <p><em>Thank you for using nginx.</em></p>
  88.         </body>
  89.         </html>
  90.         `
  91.         return text ;
  92. }
  93. export default {
  94.         async fetch(request, env, ctx) {
  95.                 const getReqHeader = (key) => request.headers.get(key); // 获取请求头
  96.                 let url = new URL(request.url); // 解析请求URL
  97.                 workers_url = `https://${url.hostname}`;
  98.                 const pathname = url.pathname;
  99.                 const hostname = url.searchParams.get('hubhost') || url.hostname;
  100.                 const hostTop = hostname.split('.')[0];// 获取主机名的第一部分
  101.                 const checkHost = routeByHosts(hostTop);
  102.                 hub_host = checkHost[0]; // 获取上游地址
  103.                 const fakePage = checkHost[1];
  104.                 console.log(`域名头部: ${hostTop}\n反代地址: ${hub_host}\n伪装首页: ${fakePage}`);
  105.                 const isUuid = isUUID(pathname.split('/')[1].split('/')[0]);
  106.                
  107.                 const conditions = [
  108.                         isUuid,
  109.                         pathname.includes('/_'),
  110.                         pathname.includes('/r'),
  111.                         pathname.includes('/v2/user'),
  112.                         pathname.includes('/v2/orgs'),
  113.                         pathname.includes('/v2/_catalog'),
  114.                         pathname.includes('/v2/categories'),
  115.                         pathname.includes('/v2/feature-flags'),
  116.                         pathname.includes('search'),
  117.                         pathname.includes('source'),
  118.                         pathname === '/',
  119.                         pathname === '/favicon.ico',
  120.                         pathname === '/auth/profile',
  121.                 ];
  122.                 if (conditions.some(condition => condition) && (fakePage === true || hostTop == 'docker')) {
  123.                         if (env.URL302){
  124.                                 return Response.redirect(env.URL302, 302);
  125.                         } else if (env.URL){
  126.                                 if (env.URL.toLowerCase() == 'nginx'){
  127.                                         //首页改成一个nginx伪装页
  128.                                         return new Response(await nginx(), {
  129.                                                 headers: {
  130.                                                         'Content-Type': 'text/html; charset=UTF-8',
  131.                                                 },
  132.                                         });
  133.                                 } else return fetch(new Request(env.URL, request));
  134.                         }
  135.                        
  136.                         const newUrl = new URL("https://registry.hub.docker.com" + pathname + url.search);
  137.                         // 复制原始请求的标头
  138.                         const headers = new Headers(request.headers);
  139.                         // 确保 Host 头部被替换为 hub.docker.com
  140.                         headers.set('Host', 'registry.hub.docker.com');
  141.                         const newRequest = new Request(newUrl, {
  142.                                         method: request.method,
  143.                                         headers: headers,
  144.                                         body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.blob() : null,
  145.                                         redirect: 'follow'
  146.                         });
  147.                         return fetch(newRequest);
  148.                 }
  149.                 // 修改包含 %2F 和 %3A 的请求
  150.                 if (!/%2F/.test(url.search) && /%3A/.test(url.toString())) {
  151.                         let modifiedUrl = url.toString().replace(/%3A(?=.*?&)/, '%3Alibrary%2F');
  152.                         url = new URL(modifiedUrl);
  153.                         console.log(`handle_url: ${url}`)
  154.                 }
  155.                 // 处理token请求
  156.                 if (url.pathname.includes('/token')) {
  157.                         let token_parameter = {
  158.                                 headers: {
  159.                                         'Host': 'auth.docker.io',
  160.                                         'User-Agent': getReqHeader("User-Agent"),
  161.                                         'Accept': getReqHeader("Accept"),
  162.                                         'Accept-Language': getReqHeader("Accept-Language"),
  163.                                         'Accept-Encoding': getReqHeader("Accept-Encoding"),
  164.                                         'Connection': 'keep-alive',
  165.                                         'Cache-Control': 'max-age=0'
  166.                                 }
  167.                         };
  168.                         let token_url = auth_url + url.pathname + url.search
  169.                         return fetch(new Request(token_url, request), token_parameter)
  170.                 }
  171.                 // 修改 /v2/ 请求路径
  172.                 if (/^\/v2\/[^/]+\/[^/]+\/[^/]+$/.test(url.pathname) && !/^\/v2\/library/.test(url.pathname)) {
  173.                         url.pathname = url.pathname.replace(/\/v2\//, '/v2/library/');
  174.                         console.log(`modified_url: ${url.pathname}`)
  175.                 }
  176.                 // 更改请求的主机名
  177.                 url.hostname = hub_host;
  178.                 // 构造请求参数
  179.                 let parameter = {
  180.                         headers: {
  181.                                 'Host': hub_host,
  182.                                 'User-Agent': getReqHeader("User-Agent"),
  183.                                 'Accept': getReqHeader("Accept"),
  184.                                 'Accept-Language': getReqHeader("Accept-Language"),
  185.                                 'Accept-Encoding': getReqHeader("Accept-Encoding"),
  186.                                 'Connection': 'keep-alive',
  187.                                 'Cache-Control': 'max-age=0'
  188.                         },
  189.                         cacheTtl: 3600 // 缓存时间
  190.                 };
  191.                 // 添加Authorization头
  192.                 if (request.headers.has("Authorization")) {
  193.                         parameter.headers.Authorization = getReqHeader("Authorization");
  194.                 }
  195.                 // 发起请求并处理响应
  196.                 let original_response = await fetch(new Request(url, request), parameter)
  197.                 let original_response_clone = original_response.clone();
  198.                 let original_text = original_response_clone.body;
  199.                 let response_headers = original_response.headers;
  200.                 let new_response_headers = new Headers(response_headers);
  201.                 let status = original_response.status;
  202.                 // 修改 Www-Authenticate 头
  203.                 if (new_response_headers.get("Www-Authenticate")) {
  204.                         let auth = new_response_headers.get("Www-Authenticate");
  205.                         let re = new RegExp(auth_url, 'g');
  206.                         new_response_headers.set("Www-Authenticate", response_headers.get("Www-Authenticate").replace(re, workers_url));
  207.                 }
  208.                 // 处理重定向
  209.                 if (new_response_headers.get("Location")) {
  210.                         return httpHandler(request, new_response_headers.get("Location"))
  211.                 }
  212.                 // 返回修改后的响应
  213.                 let response = new Response(original_text, {
  214.                         status,
  215.                         headers: new_response_headers
  216.                 })
  217.                 return response;
  218.         }
  219. };
  220. /**
  221. * 处理HTTP请求
  222. * @param {Request} req 请求对象
  223. * @param {string} pathname 请求路径
  224. */
  225. function httpHandler(req, pathname) {
  226.         const reqHdrRaw = req.headers
  227.         // 处理预检请求
  228.         if (req.method === 'OPTIONS' &&
  229.                 reqHdrRaw.has('access-control-request-headers')
  230.         ) {
  231.                 return new Response(null, PREFLIGHT_INIT)
  232.         }
  233.         let rawLen = ''
  234.         const reqHdrNew = new Headers(reqHdrRaw)
  235.         const refer = reqHdrNew.get('referer')
  236.         let urlStr = pathname
  237.         const urlObj = newUrl(urlStr)
  238.         /** @type {RequestInit} */
  239.         const reqInit = {
  240.                 method: req.method,
  241.                 headers: reqHdrNew,
  242.                 redirect: 'follow',
  243.                 body: req.body
  244.         }
  245.         return proxy(urlObj, reqInit, rawLen)
  246. }
  247. /**
  248. * 代理请求
  249. * @param {URL} urlObj URL对象
  250. * @param {RequestInit} reqInit 请求初始化对象
  251. * @param {string} rawLen 原始长度
  252. */
  253. async function proxy(urlObj, reqInit, rawLen) {
  254.         const res = await fetch(urlObj.href, reqInit)
  255.         const resHdrOld = res.headers
  256.         const resHdrNew = new Headers(resHdrOld)
  257.         // 验证长度
  258.         if (rawLen) {
  259.                 const newLen = resHdrOld.get('content-length') || ''
  260.                 const badLen = (rawLen !== newLen)
  261.                 if (badLen) {
  262.                         return makeRes(res.body, 400, {
  263.                                 '--error': `bad len: ${newLen}, except: ${rawLen}`,
  264.                                 'access-control-expose-headers': '--error',
  265.                         })
  266.                 }
  267.         }
  268.         const status = res.status
  269.         resHdrNew.set('access-control-expose-headers', '*')
  270.         resHdrNew.set('access-control-allow-origin', '*')
  271.         resHdrNew.set('Cache-Control', 'max-age=1500')
  272.         // 删除不必要的头
  273.         resHdrNew.delete('content-security-policy')
  274.         resHdrNew.delete('content-security-policy-report-only')
  275.         resHdrNew.delete('clear-site-data')
  276.         return new Response(res.body, {
  277.                 status,
  278.                 headers: resHdrNew
  279.         })
  280. }
复制代码
代码来源于GitHub:cmliu大佬的项目,可以去给他点个star


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4