搭建专属Docker镜像中转站
阅读之前
请注意:实现搭建docker镜像中转,需要满足以下条件,如不满足请不要复现浪费时间。
- 拥有一个自己的域名
- 域名通过cloudflare的DNS进行解析,可以在cloudflare中阅读帮助进行解析
注册并登录CF账号
https://dash.cloudflare.com/login?lang=zh-hans-cn
建立worker
-
创建worker
-
配置worker
-
开始编辑代码
-
编辑代码
在左侧代码去执行:
- 删除全部默认代码
- 添加以下代码
function logError(request, message) { console.error( `${message}, clientIp: ${request.headers.get( "cf-connecting-ip" )}, user-agent: ${request.headers.get("user-agent")}, url: ${request.url}` ); } function createNewRequest(request, url, proxyHostname, originHostname) { const newRequestHeaders = new Headers(request.headers); for (const [key, value] of newRequestHeaders) { if (value.includes(originHostname)) { newRequestHeaders.set( key, value.replace( new RegExp(`(?<!\\.)\\b${originHostname}\\b`, "g"), proxyHostname ) ); } } return new Request(url.toString(), { method: request.method, headers: newRequestHeaders, body: request.body, }); } function setResponseHeaders( originalResponse, proxyHostname, originHostname, DEBUG ) { const newResponseHeaders = new Headers(originalResponse.headers); for (const [key, value] of newResponseHeaders) { if (value.includes(proxyHostname)) { newResponseHeaders.set( key, value.replace( new RegExp(`(?<!\\.)\\b${proxyHostname}\\b`, "g"), originHostname ) ); } } if (DEBUG) { newResponseHeaders.delete("content-security-policy"); } let docker_auth_url = newResponseHeaders.get("www-authenticate"); if (docker_auth_url && docker_auth_url.includes("auth.docker.io/token")) { newResponseHeaders.set( "www-authenticate", docker_auth_url.replace("auth.docker.io/token", originHostname + "/token") ); } return newResponseHeaders; } /** * 替换内容 * @param originalResponse 响应 * @param proxyHostname 代理地址 hostname * @param pathnameRegex 代理地址路径匹配的正则表达式 * @param originHostname 替换的字符串 * @returns {Promise<*>} */ async function replaceResponseText( originalResponse, proxyHostname, pathnameRegex, originHostname ) { let text = await originalResponse.text(); if (pathnameRegex) { pathnameRegex = pathnameRegex.replace(/^\^/, ""); return text.replace( new RegExp(`((?<!\\.)\\b${proxyHostname}\\b)(${pathnameRegex})`, "g"), `${originHostname}$2` ); } else { return text.replace( new RegExp(`(?<!\\.)\\b${proxyHostname}\\b`, "g"), originHostname ); } } async function nginx() { return `<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>`; } export default { async fetch(request, env, ctx) { try { let { PROXY_HOSTNAME = "registry-1.docker.io", PROXY_PROTOCOL = "https", PATHNAME_REGEX, UA_WHITELIST_REGEX, UA_BLACKLIST_REGEX, URL302, IP_WHITELIST_REGEX, IP_BLACKLIST_REGEX, REGION_WHITELIST_REGEX, REGION_BLACKLIST_REGEX, DEBUG = false, } = env; const url = new URL(request.url); const originHostname = url.hostname; if (url.pathname.includes("/token")) { PROXY_HOSTNAME = "auth.docker.io"; } else if (url.pathname.includes("/search")) { PROXY_HOSTNAME = "index.docker.io"; } if ( !PROXY_HOSTNAME || (PATHNAME_REGEX && !new RegExp(PATHNAME_REGEX).test(url.pathname)) || (UA_WHITELIST_REGEX && !new RegExp(UA_WHITELIST_REGEX).test( request.headers.get("user-agent").toLowerCase() )) || (UA_BLACKLIST_REGEX && new RegExp(UA_BLACKLIST_REGEX).test( request.headers.get("user-agent").toLowerCase() )) || (IP_WHITELIST_REGEX && !new RegExp(IP_WHITELIST_REGEX).test( request.headers.get("cf-connecting-ip") )) || (IP_BLACKLIST_REGEX && new RegExp(IP_BLACKLIST_REGEX).test( request.headers.get("cf-connecting-ip") )) || (REGION_WHITELIST_REGEX && !new RegExp(REGION_WHITELIST_REGEX).test( request.headers.get("cf-ipcountry") )) || (REGION_BLACKLIST_REGEX && new RegExp(REGION_BLACKLIST_REGEX).test( request.headers.get("cf-ipcountry") )) ) { logError(request, "Invalid"); return URL302 ? Response.redirect(URL302, 302) : new Response(await nginx(), { headers: { "Content-Type": "text/html; charset=utf-8", }, }); } url.host = PROXY_HOSTNAME; url.protocol = PROXY_PROTOCOL; const newRequest = createNewRequest( request, url, PROXY_HOSTNAME, originHostname ); const originalResponse = await fetch(newRequest); const newResponseHeaders = setResponseHeaders( originalResponse, PROXY_HOSTNAME, originHostname, DEBUG ); const contentType = newResponseHeaders.get("content-type") || ""; let body; if (contentType.includes("text/")) { body = await replaceResponseText( originalResponse, PROXY_HOSTNAME, PATHNAME_REGEX, originHostname ); } else { body = originalResponse.body; } return new Response(body, { status: originalResponse.status, headers: newResponseHeaders, }); } catch (error) { logError(request, `Fetch error: ${error.message}`); return new Response("Internal Server Error", { status: 500 }); } }, };
- 点击右上角“部署”
- 点击左上角向前返回
设置worker
- 设置选项
- 添加自己的域名
配置docker镜像
- 在目标服务器配置docker镜像下载站
vi /etc/docker/daemon.json
在"registry-mirrors"字段添加自己的域名
- 拉取镜像测试
docker pull redis
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器