首页
关于
Search
1
AdGuardHome 安装及部署教程
40,700 阅读
2
搭建基于telegram的无限网盘
10,098 阅读
3
关于微软Azure学生白嫖指南
9,707 阅读
4
Oracle开放全部端口并关闭防火墙
9,495 阅读
5
最新Cloudflare免费自选IP教程(非Partner)
9,327 阅读
默认分类
技术搬砖
教学设计
故事奇谈
生活琐事
错题分析
精品软件
登录
Search
标签搜索
docker
张至顺
PHP
图床
Cloudflare
金刚长寿功
PT
qBittorrent
阿里云
onedrive
telegram
代理
青龙
python
内网穿透
一键
telegraph
ipv6
cf_workers
serv00
myedunote
累计撰写
101
篇文章
累计收到
1
条评论
首页
栏目
默认分类
技术搬砖
教学设计
故事奇谈
生活琐事
错题分析
精品软件
页面
关于
搜索到
2
篇与
cf_workers
的结果
2024-08-30
全新的Telegraph图床
介绍基于Cloudflare Workers的Telegraph图床目前提供D1和KV两个版本,二者的主要区别在于存储位置D1版本使用Cloudflare D1数据库进行存储,访问后台管理更流畅KV版本则使用Cloudflare KV空间,数据多的情况下,加载后台页面需要的时间长一点源码:https://github.com/0-RTT/telegraph 成品:https://545040.xyz/(使用D1数据库进行部署)效果图 功能支持上传大于5MB的图片。在图床界面中可以直接粘贴上传。选择图片后会自动上传,使用方便。管理界面支持查看和播放MP4文件。显示上传时间,并支持按上传时间排序。支持修改后台路径为 /admin,可在代码的第二行进行调整。图片管理功能可通过访问域名 /admin 实现,且图片支持懒加载。仅允许代理自己上传的图片,无法访问通过其他TG图床上传的链接。支持JPEG、JPG、PNG、GIF和MP4格式,GIF和MP4的大小需≤5MB。支持URL、BBCode和Markdown格式,点击对应按钮可自动复制相应格式的链接。选择图片后会自动压缩,以节省Cloudflare和Telegraph的存储空间,同时加快上传速度。对于需要自定义UI的用户,可以自行修改HTML代码,在修改html代码时能够保留项目开源地址。D1版本部署D1数据库限制D1数据库限制详情对于个人用户,500MB的免费存储空间足够用于储存图片链接使用。类别限制数据库数量50,000 (付费用户) beta / 10 (免费用户)最大数据库大小2 GB (付费用户) beta / 500 MB (免费用户)每个帐户的最大存储空间50 GB (付费用户) beta / 5 GB (免费用户)Time Travel 间隔时间 (时间点恢复)30 days (付费用户) / 7 days (免费用户)最大 Time Travel 还原操作数每 10 分钟 10 次还原(每个数据库)每个工作线程调用的查询数(读取子请求限制)50 (Bundled) / 1000 (Unbound)每个表的最大列数100每个表的最大行数无限制(不包括每个数据库的存储限制)最大字符串或 BLOB 表行大小1,000,000 bytes (1 MB)最大 SQL 语句长度100,000 bytes (100 KB)每个查询的最大绑定参数数100每个 SQL 函数的最大参数数32LIKE 或 GLOB 模式中的最大字符数(字节)50 bytes每个工作线程脚本的最大绑定数约5,000 人图片教程1、 创建D1数据库2、 数据库初始化数据库初始化命令CREATE TABLE media ( key TEXT PRIMARY KEY, timestamp INTEGER NOT NULL, url TEXT NOT NULL );3、创建Worker程序4、设置自定义域名或路由设置优选域名如果需要加速cf worker,并且域名托管在CF只需要将自定义域的解析记录删除,然后重新添加新的cname记录到任意优选CNAME域名即可(不要勾选小云朵,选择仅DNS) 优质优选cname地址如下 https://monitor.gacjie.cn/page/cloudflare/cname.html进入该管理域名内,左侧有个worker路由,将刚刚优选的二级域名(后面最好加/*)填入这个路由中,然后worker选择指向,选择刚刚创建的,最后手动访问一次网站即可5、设置后台管理环境变量环境变量设置账号USERNAME 环境变量设置密码PASSWORD数据库绑定变量DATABASE KV版本部署KV限制KV键值限制详情对于个人用户,免费额度足够用于储存图片链接使用。类别免费用户付费用户读每天 100,000 次读取无限写入不同的键每天 1,000 次写入无限写入同一密钥每秒 1 次每秒 1 次操作/worker调用10001000命名空间100100存储/帐户1 GB无限存储/命名空间1 GB无限键/命名空间无限无限键大小512 bytes512 bytes键元数据1024 bytes1024 bytes值大小25 MiB25 MiB使用方法将代码部署到 Cloudflare Worker,设置自定义域和变量(需要设置环境变量并绑定 KV 命名空间)。步骤 1: 创建 KV 命名空间点击 Workers 和 Pages。点击 KV。点击 创建命名空间。填写命名空间名称(可随意命名)。点击 添加。步骤 2: 创建 Worker点击 Workers 和 Pages。点击 创建。填写 Worker 名称(可随意命名)。点击 部署。步骤 3: 添加自定义域点击刚刚创建的 Worker 名称。点击 设置。点击 触发器。点击 添加自定义域。步骤 4: 添加环境变量点击刚刚创建的 Worker 名称。点击 设置。点击 变量。点击 添加环境变量。填写两个环境变量:USERNAME和PASSWORD,分别对应的值为账号和密码。步骤 5: 绑定 KV 命名空间点击刚刚创建的 Worker 名称。点击 设置。点击 变量。点击 KV 命名空间绑定。点击 编辑变量。填写变量名称 imgurl,并选择前面设置的 KV 命名空间。步骤 6: 编辑 Worker 代码点击刚刚创建的 Worker 名称。点击 编辑代码。清除 Worker 原本的代码。复制粘贴 worker.js 中的代码。将代码第一行中的example.com改为你的自定义域。点击 部署。访问自定义域名即可访问图床。参考链接1、利用D1数据库储存Telegraph图床链接 ,超详细的图片教程2、分享一下我个人使用CF优选的经验和方法
2024年08月30日
88 阅读
0 评论
0 点赞
2024-06-27
国内无法访问下载 Docker 镜像的多种解决方案
简介2023 年 5 月, hub.docker.com "不知" 何种原因国内均无法正常访问了。当时只是官网不能访问,但不影响 pull 镜像。2024年6月7日,GFW正式DNS污染+SNI阻断了docker.com及其相关域名。从国内解析得到的IP地址为Twitter/Facebook的IP,符合大墙DNS污染的特征。而如果使用海外解析得到的正常IP地址从国内访问则会被SNI重置阻断链接。2024 年 6 月,国内几家 Docker Hub 镜像服务平台均发公告说 "被" 要求下架,停止服务。不知以后是否开放?或开启白名单模式?与此同时,上交镜像站等一系列中国大陆公益镜像站点也“接上级主管部门通知,暂时关闭 Docker Hub 镜像缓存服务”。(通知链接 1 2)更新:南京大学、中科大、上海交大 目前明确停止docker镜像 网易之前死了 腾讯微软据说内网可用 阿里登陆后就可以拿到子域名 百度好像也挂了 dockerproxy被墙这里不讨论其原因!这里分享几个便捷方法,帮助有需求的朋友正常的拉取 Docker 镜像!零门槛境外镜像优点:不需大量修改,只需几个命令缺点:网络可能慢或者不稳定下面命令可直接执行~sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": [ "https://docker.m.daocloud.io", "https://huecker.io", "https://dockerhub.timeweb.cloud", "https://noohub.ru" ] } EOF sudo systemctl daemon-reload sudo systemctl restart docker命令行执行 docker info,如果从结果中看到了如下内容,说明配置成功。Registry Mirrors: [...] https://docker.m.daocloud.ioDocker Hub 镜像加速器列表以下镜像站来源于互联网(感谢热心网友),可能出现宕机、转内网、关停等情况,建议同时配置多个镜像源。2024年6月27日 亲测可用镜像加速器地址其他说明https://dockerpull.comCF的workers来搭建https://dockerproxy.cnCF的workers来搭建https://docker.1panel.live1Panel 面板提供(推荐)https://hub.rat.dev耗子面板提供https://docker.chenby.cnDocker Hubhttps://docker.anyhub.us.kgDockerHub 镜像加速代理https://dockerhub.icuDocker镜像加速站https://docker.ckyl.meDocker镜像加速站https://dockerhub.jobcher.comDocker Hubhttps://docker.hpcloud.cloud镜像使用说明https://docker.awsl9527.cn镜像使用说明https://www.hallodocker.com/镜像使用说明Yandex 容器加速优点:适合单独 pull 镜像使用,俄罗斯大厂提供服务缺点:不支持配置到 daemon.json官方镜像:https://mirror.yandex.ru/使用方式:docker pull cr.yandex/mirror/nginx低门槛Docker 使用 HTTP 代理优点:可从 Docker 官方直接拉取这里主要介绍如何让服务器的 Docker Pull 的时候能走代理!1,新建目录mkdir -p /etc/systemd/system/docker.service.d2,新建文件,粘贴并内容,并保存!vim /etc/systemd/system/docker.service.d/http-proxy.conf以下粘贴内容,IP 一定要换成你代理软件运行的电脑的内网 IP,通过 ipconfig 可以查看端口一定要是代理软件设置的局域网端口![Service] Environment="HTTP_PROXY=http://USERNAME:PASSWORD@[your.proxy.server]:[port]" Environment="HTTPS_PROXY=http://USERNAME:PASSWORD@[your.proxy.server]:[port]0" Environment="NO_PROXY=localhost,127.0.0.1,.example.com"3,重启 Dockersystemctl daemon-reload systemctl restart docker4,检查环境变量是否生效systemctl show --property=Environment docker高门槛Cloudflare 反向代理优点:只需有 CF 账号就行,自己专属,不用自己签发证书缺点:CF 在国内有 DNS 污染,可能无法正常访问简要步骤:1,登录到 CFhttps://dash.cloudflare.com/2,创建Workers控制台面板 -> 左侧 Workers 和 Pages -> 创建应用程序 -> 创建 Worker -> 点击保存 -> 点击完成 -> 编辑代码worker.js 内容 // _worker.js // Docker镜像仓库主机地址 let hub_host = 'registry-1.docker.io'; // Docker认证服务器地址 const auth_url = 'https://auth.docker.io'; // 自定义的工作服务器地址 let workers_url = 'https://hub.ixm.pw/'; let 屏蔽爬虫UA = ['netcraft']; // 根据主机名选择对应的上游地址 function routeByHosts(host) { // 定义路由表 const routes = { // 生产环境 "quay": "quay.io", "gcr": "gcr.io", "k8s-gcr": "k8s.gcr.io", "k8s": "registry.k8s.io", "ghcr": "ghcr.io", "cloudsmith": "docker.cloudsmith.io", "nvcr": "nvcr.io", // 测试环境 "test": "registry-1.docker.io", }; if (host in routes) return [ routes[host], false ]; else return [ hub_host, true ]; } /** @type {RequestInit} */ const PREFLIGHT_INIT = { // 预检请求配置 headers: new Headers({ 'access-control-allow-origin': '*', // 允许所有来源 'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS', // 允许的HTTP方法 '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 }) // 返回新构造的响应 } /** * 构造新的URL对象 * @param {string} urlStr URL字符串 */ function newUrl(urlStr) { try { return new URL(urlStr) // 尝试构造新的URL对象 } catch (err) { return null // 构造失败返回null } } function isUUID(uuid) { // 定义一个正则表达式来匹配 UUID 格式 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; // 使用正则表达式测试 UUID 字符串 return uuidRegex.test(uuid); } async function nginx() { const text = ` <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> 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> ` return text; } async function searchInterface() { const text = ` <!DOCTYPE html> <html> <head> <title>Docker Hub Search</title> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; background: linear-gradient(to right, rgb(28, 143, 237), rgb(29, 99, 237)); } .logo { margin-bottom: 20px; } .search-container { display: flex; align-items: center; } #search-input { padding: 10px; font-size: 16px; border: 1px solid #ddd; border-radius: 4px; width: 300px; margin-right: 10px; } #search-button { padding: 10px; background-color: rgba(255, 255, 255, 0.2); /* 设置白色,透明度为10% */ border: none; border-radius: 4px; cursor: pointer; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; } #search-button svg { width: 24px; height: 24px; } </style> </head> <body> <div class="logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 18" fill="#ffffff" width="100" height="75"> <path d="M23.763 6.886c-.065-.053-.673-.512-1.954-.512-.32 0-.659.03-1.01.087-.248-1.703-1.651-2.533-1.716-2.57l-.345-.2-.227.328a4.596 4.596 0 0 0-.611 1.433c-.23.972-.09 1.884.403 2.666-.596.331-1.546.418-1.744.42H.752a.753.753 0 0 0-.75.749c-.007 1.456.233 2.864.692 4.07.545 1.43 1.355 2.483 2.409 3.13 1.181.725 3.104 1.14 5.276 1.14 1.016 0 2.03-.092 2.93-.266 1.417-.273 2.705-.742 3.826-1.391a10.497 10.497 0 0 0 2.61-2.14c1.252-1.42 1.998-3.005 2.553-4.408.075.003.148.005.221.005 1.371 0 2.215-.55 2.68-1.01.505-.5.685-.998.704-1.053L24 7.076l-.237-.19Z"></path> <path d="M2.216 8.075h2.119a.186.186 0 0 0 .185-.186V6a.186.186 0 0 0-.185-.186H2.216A.186.186 0 0 0 2.031 6v1.89c0 .103.083.186.185.186Zm2.92 0h2.118a.185.185 0 0 0 .185-.186V6a.185.185 0 0 0-.185-.186H5.136A.185.185 0 0 0 4.95 6v1.89c0 .103.083.186.186.186Zm2.964 0h2.118a.186.186 0 0 0 .185-.186V6a.186.186 0 0 0-.185-.186H8.1A.185.185 0 0 0 7.914 6v1.89c0 .103.083.186.186.186Zm2.928 0h2.119a.185.185 0 0 0 .185-.186V6a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm-5.892-2.72h2.118a.185.185 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186H5.136a.186.186 0 0 0-.186.186v1.89c0 .103.083.186.186.186Zm2.964 0h2.118a.186.186 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186H8.1a.186.186 0 0 0-.186.186v1.89c0 .103.083.186.186.186Zm2.928 0h2.119a.185.185 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm0-2.72h2.119a.186.186 0 0 0 .185-.186V.56a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm2.955 5.44h2.118a.185.185 0 0 0 .186-.186V6a.185.185 0 0 0-.186-.186h-2.118a.185.185 0 0 0-.185.186v1.89c0 .103.083.186.185.186Z"></path> </svg> </div> <div class="search-container"> <input type="text" id="search-input" placeholder="Search Docker Hub"> <button id="search-button"> <svg focusable="false" aria-hidden="true" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M21 21L16.65 16.65M19 11C19 15.4183 15.4183 19 11 19C6.58172 19 3 15.4183 3 11C3 6.58172 6.58172 3 11 3C15.4183 3 19 6.58172 19 11Z" stroke="white" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> </svg> </button> </div> <script> function performSearch() { const query = document.getElementById('search-input').value; if (query) { window.location.href = '/search?q=' + encodeURIComponent(query); } } document.getElementById('search-button').addEventListener('click', performSearch); document.getElementById('search-input').addEventListener('keypress', function(event) { if (event.key === 'Enter') { performSearch(); } }); </script> </body> </html> `; return text; } export default { async fetch(request, env, ctx) { const getReqHeader = (key) => request.headers.get(key); // 获取请求头 let url = new URL(request.url); // 解析请求URL const userAgentHeader = request.headers.get('User-Agent'); const userAgent = userAgentHeader ? userAgentHeader.toLowerCase() : "null"; if (env.UA) 屏蔽爬虫UA = 屏蔽爬虫UA.concat(await ADD(env.UA)); workers_url = `https://${url.hostname}`; const pathname = url.pathname; // 获取请求参数中的 ns const ns = url.searchParams.get('ns'); const hostname = url.searchParams.get('hubhost') || url.hostname; const hostTop = hostname.split('.')[0]; // 获取主机名的第一部分 let checkHost; // 在这里定义 checkHost 变量 // 如果存在 ns 参数,优先使用它来确定 hub_host if (ns) { if (ns === 'docker.io') { hub_host = 'registry-1.docker.io'; // 设置上游地址为 registry-1.docker.io } else { hub_host = ns; // 直接使用 ns 作为 hub_host } } else { checkHost = routeByHosts(hostTop); hub_host = checkHost[0]; // 获取上游地址 } const fakePage = checkHost ? checkHost[1] : false; // 确保 fakePage 不为 undefined console.log(`域名头部: ${hostTop}\n反代地址: ${hub_host}\n伪装首页: ${fakePage}`); const isUuid = isUUID(pathname.split('/')[1].split('/')[0]); if (屏蔽爬虫UA.some(fxxk => userAgent.includes(fxxk)) && 屏蔽爬虫UA.length > 0) { // 首页改成一个nginx伪装页 return new Response(await nginx(), { headers: { 'Content-Type': 'text/html; charset=UTF-8', }, }); } const conditions = [ isUuid, pathname.includes('/_'), pathname.includes('/r/'), pathname.includes('/v2/user'), pathname.includes('/v2/orgs'), pathname.includes('/v2/_catalog'), pathname.includes('/v2/categories'), pathname.includes('/v2/feature-flags'), pathname.includes('search'), pathname.includes('source'), pathname === '/', pathname === '/favicon.ico', pathname === '/auth/profile', ]; if (conditions.some(condition => condition) && (fakePage === true || hostTop == 'docker')) { if (env.URL302) { return Response.redirect(env.URL302, 302); } else if (env.URL) { if (env.URL.toLowerCase() == 'nginx') { //首页改成一个nginx伪装页 return new Response(await nginx(), { headers: { 'Content-Type': 'text/html; charset=UTF-8', }, }); } else return fetch(new Request(env.URL, request)); } else if (url.pathname == '/'){ return new Response(await searchInterface(), { headers: { 'Content-Type': 'text/html; charset=UTF-8', }, }); } const newUrl = new URL("https://registry.hub.docker.com" + pathname + url.search); // 复制原始请求的标头 const headers = new Headers(request.headers); // 确保 Host 头部被替换为 hub.docker.com headers.set('Host', 'registry.hub.docker.com'); const newRequest = new Request(newUrl, { method: request.method, headers: headers, body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.blob() : null, redirect: 'follow' }); return fetch(newRequest); } // 修改包含 %2F 和 %3A 的请求 if (!/%2F/.test(url.search) && /%3A/.test(url.toString())) { let modifiedUrl = url.toString().replace(/%3A(?=.*?&)/, '%3Alibrary%2F'); url = new URL(modifiedUrl); console.log(`handle_url: ${url}`); } // 处理token请求 if (url.pathname.includes('/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, request), token_parameter); } // 修改 /v2/ 请求路径 if ( hub_host == 'registry-1.docker.io' && /^\/v2\/[^/]+\/[^/]+\/[^/]+$/.test(url.pathname) && !/^\/v2\/library/.test(url.pathname)) { //url.pathname = url.pathname.replace(/\/v2\//, '/v2/library/'); url.pathname = '/v2/library/' + url.pathname.split('/v2/')[1]; console.log(`modified_url: ${url.pathname}`); } // 更改请求的主机名 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 // 缓存时间 }; // 添加Authorization头 if (request.headers.has("Authorization")) { parameter.headers.Authorization = getReqHeader("Authorization"); } // 发起请求并处理响应 let original_response = await fetch(new Request(url, 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; // 修改 Www-Authenticate 头 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(request, new_response_headers.get("Location")); } // 返回修改后的响应 let response = new Response(original_text, { status, headers: new_response_headers }); return response; } }; /** * 处理HTTP请求 * @param {Request} req 请求对象 * @param {string} pathname 请求路径 */ 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); 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); } /** * 代理请求 * @param {URL} urlObj URL对象 * @param {RequestInit} reqInit 请求初始化对象 * @param {string} 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 }); } async function ADD(envadd) { var addtext = envadd.replace(/[ |"'\r\n]+/g, ',').replace(/,+/g, ','); // 将空格、双引号、单引号和换行符替换为逗号 if (addtext.charAt(0) == ',') addtext = addtext.slice(1); if (addtext.charAt(addtext.length - 1) == ',') addtext = addtext.slice(0, addtext.length - 1); const add = addtext.split(','); return add; }修改自定义域名 需要是托管dns在cloudflare的域名才可以3,点击部署即可,右上角 deploy保存4,绑定自定义域名设置 -> 触发器 -> 自定义域 -> 点击【添加自定义域】这里添加上自定义域名 [假如我的是mirrors.dockerpull.com]保存 大功告成 现在可以用这个自定义的域名访问了演示地址:dockerhub.o0o.us.kg接下来还有可以选择开启的环境变量功能 就是伪装首页变量说明变量名示例备注URL302https://baidu.com主页302跳转URLhttps://dockerpull.com 121主页伪装(设为nginx则伪装为nginx默认页面)如果你像我的dockerpull.com 40无所畏惧 就可以不管 如果你想自己稳定使用 不想公开的话 可以设置伪装页面 找到设置 环境变量如果想别人访问域名首页的时候重定向到别的网站 可以加入环境变量URL302必须要大写的哈 然后值填写需要目标域名 我以跳转到百度为例保存之后 访问首页就会自动跳转到百度 但是拉取docker镜像的时候 不会受到影响第二种 是伪装首页 可以伪装成任意的网页首页 变量名称改为URL 也是要大写 值输入https://dockerpull.com 保存这时候访问域名 就会出现我的那个镜像站的页面,当然也可以用别的页面使用服务器自建优点:需要有境外服务器缺点:网络可能慢或者不稳定这种方法需要自己有一台境外服务器,签发域名证书。按下面配置即可!工作原理当您首次从本地注册表镜像请求图像时,它会从公共Docker注册表中拉取图像,并在将其返回给您之前将其存储在本地。在后续的请求中,本地注册表镜像可以从自己的存储中提供图像。前期准备1.一个没有被墙的、延迟和带宽较好的非大陆小鸡(墙了的话可以试试套cf)2.一个域名,无需备案,解析到你的小鸡的ip上,申请好证书,后续反代需要3.安装好了docker及docker-composedocker安装docker-compose安装首先创建一个docker-compose文件vi registry/docker-compose.yml然后粘贴如下内容#version: '3' #最新版本docker 不在需要此字段 services: registry: image: registry:2 ports: - "15000:5000" environment: REGISTRY_PROXY_REMOTEURL: https://registry-1.docker.io # 上游源 REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR: inmemory # 内存缓存 volumes: - ./data:/var/lib/registry使用docker-compose命令一键启动docker-compose up -d反向代理需要注意的是如果仅仅作为镜像源,需要把push功能ban掉,推荐使用nginx反代的时候禁止其他http method# 端口, 域名 都改为自己的 server { listen 80; server_name my-registry-domain.com; location / { # 仅允许 GET 请求 limit_except GET { deny all; } proxy_pass http://localhost:15000; # 假设 Docker Registry 运行在本地的 15000 端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }项目脚本部署GitHub项目地址:https://github.com/dqzboy/Docker-Proxy一键脚本执行✨️ 一键部署Docker镜像代理服务的功能,支持基于官方Docker Registry的镜像代理.✨️ 支持多个镜像仓库的代理,包括Docker Hub、GitHub Container Registry (ghcr.io)、Quay Container Registry (quay.io)和 Kubernetes Container Registry (k8s.gcr.io)✨️ 自动检查并安装所需的依赖软件,如Docker、Nginx等,并确保系统环境满足运行要求.✨️ 自动清理注册表上传目录中的那些不再被任何镜像或清单引用的文件✨️ 提供了重启服务、更新服务、更新配置和卸载服务的功能,方便用户进行日常管理和维护✨️ 支持主流Linux发行版操作系统,例如centos、Ubuntu、Rocky、Debian、Rhel等✨️ 支持主流ARCH架构下部署,包括linux/amd64、linux/arm64# CentOS yum -y install wget curl # ubuntu apt -y install wget curl bash -c "$(curl -fsSL https://raw.githubusercontent.com/dqzboy/Docker-Proxy/main/install/DockerProxy_Install.sh)"配置nginx反向代理### docker hub 51000 ### gchr 52000 ### gcr 53000 ### k8s-gcr 54000 ### quay 55000 location ^~ / { proxy_pass http://127.0.0.1:51000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; add_header X-Cache $upstream_cache_status; add_header Strict-Transport-Security "max-age=31536000"; }直接nginx反代这里博主并未测试,下面内容仅供参考# 使用 map 来匹配和替换 upstream 头部中的 auth.docker.io map $upstream_http_www_authenticate $m_www_authenticate_replaced { "~auth\.docker\.io(.*)" "$1"; default ""; } map $m_www_authenticate_replaced $m_final_replaced { "~(.*)" 'Bearer realm=\"$scheme://$host$1'; default ""; } server { listen 80; listen 443 ssl http2; server_name 域名; #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则 #error_page 404/404.html; ssl_certificate 证书地址; ssl_certificate_key 秘钥地址; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; add_header Strict-Transport-Security "max-age=31536000"; error_page 497 https://$host$request_uri; #SSL-END proxy_ssl_server_name on; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 修改jwt授权地址 proxy_hide_header www-authenticate; add_header www-authenticate "$m_final_replaced" always; # 关闭缓存 proxy_buffering off; # 转发认证相关 proxy_set_header Authorization $http_authorization; proxy_pass_header Authorization; # 对 upstream 状态码检查,实现 error_page 错误重定向 proxy_intercept_errors on; recursive_error_pages on; # 根据状态码执行对应操作,以下为301、302、307状态码都会触发 error_page 301 302 307 = @handle_redirect; # v1 api location /v1 { proxy_pass https://index.docker.io; proxy_set_header Host index.docker.io; } # v2 api location /v2 { proxy_pass https://index.docker.io; proxy_set_header Host index.docker.io; } # jwt授权地址 location /token { proxy_pass https://auth.docker.io; proxy_set_header Host auth.docker.io; } location / { # Docker hub 的官方镜像仓库 proxy_pass https://registry-1.docker.io; proxy_set_header Host registry-1.docker.io; } location @handle_redirect { resolver 1.1.1.1; set $saved_redirect_location '$upstream_http_location'; proxy_pass $saved_redirect_location; }其他开源项目https://github.com/NoCLin/LightMirrorshttps://github.com/bboysoulcn/registry-mirror最后总结1,如临时使用,建议参与零门槛几个方案,方便快捷2,据说后面 pip 源可能也会受到影响,可用采用 HTTP 代理方式
2024年06月27日
856 阅读
0 评论
2 点赞