index.html
                        
                             · 3.3 KiB · HTML
                        
                    
                    
                      
                        Bruto
                      
                    
                      
                    
                        
                          
                        
                    
                    
                
                
                
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>V2镜像使用说明</title>
    <style>
        body {
            font-family: 'Roboto', sans-serif;
            margin: 0;
            padding: 0;
            background: linear-gradient(135deg, #e0f7fa, #e1bee7);
            color: #333;
        }
        .header {
            background: linear-gradient(135deg, #667eea, #764ba2);
            color: #fff;
            padding: 20px 0;
            text-align: center;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            animation: fadeIn 1.5s;
        }
        .container {
            max-width: 800px;
            margin: 40px auto;
            padding: 20px;
            background-color: #fff;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            border-radius: 10px;
            animation: slideInUp 1s;
        }
        .content {
            margin-bottom: 20px;
        }
        .footer {
            text-align: center;
            padding: 20px 0;
            background-color: #333;
            color: #fff;
            animation: fadeIn 1.5s;
        }
        pre {
            background-color: #272822;
            color: #f8f8f2;
            padding: 15px;
            border-radius: 5px;
            overflow-x: auto;
        }
        code {
            font-family: 'Source Code Pro', monospace;
        }
        a {
            color: #4CAF50;
            text-decoration: none;
            transition: color 0.3s;
        }
        a:hover {
            color: #388E3C;
            text-decoration: underline;
        }
        @media (max-width: 600px) {
            .container {
                margin: 20px;
                padding: 15px;
            }
            .header {
                padding: 15px 0;
            }
        }
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
        @keyframes slideInUp {
            from { transform: translateY(20px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }
    </style>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Source+Code+Pro:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
    <div class="header">
        <h1>ghcr镜像使用说明</h1>
    </div>
    <div class="container">
        <div class="content">
            <p>为了加速镜像拉取,你可以使用以下命令设置 registry mirror:</p>
            <pre><code>sudo tee /etc/docker/daemon.json <<EOF
{
    "registry-mirrors": ["https://{{host}}"]
}
EOF</code></pre>
            <p>为了避免 Worker 用量耗尽,你可以手动 pull 镜像然后 re-tag 之后 push 至本地镜像仓库:</p>
            <pre><code>docker pull {{host}}/library/alpine:latest # 拉取 library 镜像
docker pull {{host}}/coredns/coredns:latest # 拉取 coredns 镜像</code></pre>
        </div>
    </div>
    <div class="footer">
        <p>Powered by Cloudflare Workers</p>
        <p>免责声明:本服务及其内容按“现状”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、适用性的任何保证。使用本服务存在的风险由用户自行承担。</p>
    </div>
</body>
</html>
                | 1 | <!DOCTYPE html> | 
| 2 | <html lang="zh-CN"> | 
| 3 | <head> | 
| 4 | <meta charset="utf-8"> | 
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1"> | 
| 6 | <title>V2镜像使用说明</title> | 
| 7 | <style> | 
| 8 | body { | 
| 9 | font-family: 'Roboto', sans-serif; | 
| 10 | margin: 0; | 
| 11 | padding: 0; | 
| 12 | background: linear-gradient(135deg, #e0f7fa, #e1bee7); | 
| 13 | color: #333; | 
| 14 | } | 
| 15 | .header { | 
| 16 | background: linear-gradient(135deg, #667eea, #764ba2); | 
| 17 | color: #fff; | 
| 18 | padding: 20px 0; | 
| 19 | text-align: center; | 
| 20 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | 
| 21 | animation: fadeIn 1.5s; | 
| 22 | } | 
| 23 | .container { | 
| 24 | max-width: 800px; | 
| 25 | margin: 40px auto; | 
| 26 | padding: 20px; | 
| 27 | background-color: #fff; | 
| 28 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | 
| 29 | border-radius: 10px; | 
| 30 | animation: slideInUp 1s; | 
| 31 | } | 
| 32 | .content { | 
| 33 | margin-bottom: 20px; | 
| 34 | } | 
| 35 | .footer { | 
| 36 | text-align: center; | 
| 37 | padding: 20px 0; | 
| 38 | background-color: #333; | 
| 39 | color: #fff; | 
| 40 | animation: fadeIn 1.5s; | 
| 41 | } | 
| 42 | pre { | 
| 43 | background-color: #272822; | 
| 44 | color: #f8f8f2; | 
| 45 | padding: 15px; | 
| 46 | border-radius: 5px; | 
| 47 | overflow-x: auto; | 
| 48 | } | 
| 49 | code { | 
| 50 | font-family: 'Source Code Pro', monospace; | 
| 51 | } | 
| 52 | a { | 
| 53 | color: #4CAF50; | 
| 54 | text-decoration: none; | 
| 55 | transition: color 0.3s; | 
| 56 | } | 
| 57 | a:hover { | 
| 58 | color: #388E3C; | 
| 59 | text-decoration: underline; | 
| 60 | } | 
| 61 | @media (max-width: 600px) { | 
| 62 | .container { | 
| 63 | margin: 20px; | 
| 64 | padding: 15px; | 
| 65 | } | 
| 66 | .header { | 
| 67 | padding: 15px 0; | 
| 68 | } | 
| 69 | } | 
| 70 | @keyframes fadeIn { | 
| 71 | from { opacity: 0; } | 
| 72 | to { opacity: 1; } | 
| 73 | } | 
| 74 | @keyframes slideInUp { | 
| 75 | from { transform: translateY(20px); opacity: 0; } | 
| 76 | to { transform: translateY(0); opacity: 1; } | 
| 77 | } | 
| 78 | </style> | 
| 79 | <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Source+Code+Pro:wght@400;700&display=swap" rel="stylesheet"> | 
| 80 | </head> | 
| 81 | <body> | 
| 82 | <div class="header"> | 
| 83 | <h1>ghcr镜像使用说明</h1> | 
| 84 | </div> | 
| 85 | <div class="container"> | 
| 86 | <div class="content"> | 
| 87 | <p>为了加速镜像拉取,你可以使用以下命令设置 registry mirror:</p> | 
| 88 | <pre><code>sudo tee /etc/docker/daemon.json <<EOF | 
| 89 | { | 
| 90 | "registry-mirrors": ["https://{{host}}"] | 
| 91 | } | 
| 92 | EOF</code></pre> | 
| 93 | <p>为了避免 Worker 用量耗尽,你可以手动 pull 镜像然后 re-tag 之后 push 至本地镜像仓库:</p> | 
| 94 | <pre><code>docker pull {{host}}/library/alpine:latest # 拉取 library 镜像 | 
| 95 | docker pull {{host}}/coredns/coredns:latest # 拉取 coredns 镜像</code></pre> | 
| 96 | </div> | 
| 97 | </div> | 
| 98 | <div class="footer"> | 
| 99 | <p>Powered by Cloudflare Workers</p> | 
| 100 | <p>免责声明:本服务及其内容按“现状”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、适用性的任何保证。使用本服务存在的风险由用户自行承担。</p> | 
| 101 | </div> | 
| 102 | </body> | 
| 103 | </html> | 
| 104 | 
                    
                        
                        worker.js
                        
                             · 1.4 KiB · JavaScript
                        
                    
                    
                      
                        Bruto
                      
                    
                      
                    
                        
                          
                        
                    
                    
                
                
                
            import HTML from './index.html';
export default {
    async fetch(request) {
        const url = new URL(request.url);
        const path = url.pathname;
        const originalHost = request.headers.get("host");
        const registryHost = "ghcr.io";
        if (path.startsWith("/v2/")) {
            const headers = new Headers(request.headers);
            headers.set("host", registryHost);
            const registryUrl = `https://${registryHost}${path}`;
            const registryRequest = new Request(registryUrl, {
                method: request.method,
                headers: headers,
                body: request.body,
                redirect: "follow",
            });
            const registryResponse = await fetch(registryRequest);
            const responseHeaders = new Headers(registryResponse.headers);
            responseHeaders.set("access-control-allow-origin", originalHost);
            responseHeaders.set("access-control-allow-headers", "Authorization");
            return new Response(registryResponse.body, {
                status: registryResponse.status,
                statusText: registryResponse.statusText,
                headers: responseHeaders,
            });
        } else {
            return new Response(HTML.replace(/{{host}}/g, originalHost), {
                status: 200,
                headers: {
                    "content-type": "text/html"
                }
            });
        }
    }
}
                | 1 | import HTML from './index.html'; | 
| 2 | |
| 3 | export default { | 
| 4 | async fetch(request) { | 
| 5 | const url = new URL(request.url); | 
| 6 | const path = url.pathname; | 
| 7 | const originalHost = request.headers.get("host"); | 
| 8 | const registryHost = "ghcr.io"; | 
| 9 | |
| 10 | if (path.startsWith("/v2/")) { | 
| 11 | const headers = new Headers(request.headers); | 
| 12 | headers.set("host", registryHost); | 
| 13 | |
| 14 | const registryUrl = `https://${registryHost}${path}`; | 
| 15 | const registryRequest = new Request(registryUrl, { | 
| 16 | method: request.method, | 
| 17 | headers: headers, | 
| 18 | body: request.body, | 
| 19 | redirect: "follow", | 
| 20 | }); | 
| 21 | |
| 22 | const registryResponse = await fetch(registryRequest); | 
| 23 | const responseHeaders = new Headers(registryResponse.headers); | 
| 24 | responseHeaders.set("access-control-allow-origin", originalHost); | 
| 25 | responseHeaders.set("access-control-allow-headers", "Authorization"); | 
| 26 | |
| 27 | return new Response(registryResponse.body, { | 
| 28 | status: registryResponse.status, | 
| 29 | statusText: registryResponse.statusText, | 
| 30 | headers: responseHeaders, | 
| 31 | }); | 
| 32 | } else { | 
| 33 | return new Response(HTML.replace(/{{host}}/g, originalHost), { | 
| 34 | status: 200, | 
| 35 | headers: { | 
| 36 | "content-type": "text/html" | 
| 37 | } | 
| 38 | }); | 
| 39 | } | 
| 40 | } | 
| 41 | } | 
| 42 |