Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Help html for cloudflare-docker-proxy and Enable Workers Logs #74

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions src/help.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>镜像使用说明</title>
<style>
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
.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);
position: relative;
}
.github-link {
position: absolute;
top: 10px;
right: 20px;
color: #fff;
text-decoration: none;
}
.github-icon {
width: 24px;
height: 24px;
vertical-align: middle;
}
.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;
}
.content {
margin-bottom: 20px;
}
.footer {
text-align: center;
padding: 20px 0;
background-color: #333;
color: #fff;
}
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;
}
a:hover {
text-decoration: underline;
}
@media (max-width: 600px) {
.container {
margin: 20px;
padding: 15px;
}
.header {
padding: 15px 0;
}
}
</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>镜像使用说明</h1>
<a href="https://github.com/lixd/cloudflare-docker-proxy" target="_blank" class="github-link">
<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub" class="github-icon">
</a>
</div>
<div class="container">
<div class="content">
<p>为了加速 Docker 镜像拉取,你可以使用以下命令设置 registry mirror:</p>
<pre><code id="registry-config">sudo tee /etc/docker/daemon.json &lt;&lt;EOF
{
"registry-mirrors": ["https://{{host}}"]
}
EOF
# 配置完后需要重启 Docker 服务
sudo systemctl restart docker
</code></pre>
<p>使用该代理从不同的镜像仓库拉取镜像,请参考以下命令:</p>
<pre><code id="commands">
# docker pull nginx:latest
docker pull docker.{{host}}/library/nginx:latest # 拉取 Docker 官方镜像

# docker pull quay.io/coreos/etcd:latest
docker pull quay.{{host}}/coreos/etcd:latest # 拉取 Quay 镜像

# docker pull gcr.io/google-containers/busybox:latest
docker pull gcr.{{host}}/google-containers/busybox:latest # 拉取 GCR 镜像

# docker pull k8s.gcr.io/pause:latest
docker pull k8s-gcr.{{host}}/pause:latest # 拉取 k8s.gcr.io 镜像

# docker pull registry.k8s.io/pause:latest
docker pull k8s.{{host}}/pause:latest # 拉取 registry.k8s.io 镜像

# docker pull ghcr.io/github/super-linter:latest
docker pull ghcr.{{host}}/github/super-linter:latest # 拉取 GitHub 容器镜像

# docker pull docker.cloudsmith.io/public/repo/image:latest
docker pull cloudsmith.{{host}}/public/repo/image:latest # 拉取 Cloudsmith 镜像
</code></pre>
<p>为了避免 Worker 用量耗尽,你可以手动 pull 镜像然后 re-tag 之后 push 至本地镜像仓库。</p>
</div>
</div>
<div class="footer">
<p>Powered by Cloudflare Workers</p>
<!-- <p><a href="https://lixueduan.com" target="_blank">访问博客 探索云原生</a></p> -->
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const host = window.location.hostname;
const mainDomain = host.split('.').slice(-2).join('.');
const registryConfigElement = document.getElementById('registry-config');
const commandsElement = document.getElementById('commands');

registryConfigElement.innerHTML = registryConfigElement.innerHTML.replace(/{{host}}/g, host);
commandsElement.innerHTML = commandsElement.innerHTML.replace(/{{host}}/g, mainDomain);
});
</script>
</body>
</html>
73 changes: 68 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import DOCS from "./help.html";

addEventListener("fetch", (event) => {
event.passThroughOnException();
event.respondWith(handleRequest(event.request));
});

const dockerHub = "https://registry-1.docker.io";
const registry_dockerHub = "https://registry-1.docker.io";
const index_dockerHub = "https://index.docker.io";
const registry_quay = "https://quay.io";
const index_quay = "https://quay.io";

const routes = {
// production
["docker." + CUSTOM_DOMAIN]: dockerHub,
["docker." + CUSTOM_DOMAIN]: registry_dockerHub,
["quay." + CUSTOM_DOMAIN]: "https://quay.io",
["gcr." + CUSTOM_DOMAIN]: "https://gcr.io",
["k8s-gcr." + CUSTOM_DOMAIN]: "https://k8s.gcr.io",
Expand All @@ -17,7 +22,7 @@ const routes = {
["ecr." + CUSTOM_DOMAIN]: "https://public.ecr.aws",

// staging
["docker-staging." + CUSTOM_DOMAIN]: dockerHub,
["docker-staging." + CUSTOM_DOMAIN]: registry_dockerHub,
};

function routeByHosts(host) {
Expand All @@ -43,8 +48,64 @@ async function handleRequest(request) {
}
);
}
const isDockerHub = upstream == dockerHub;
// return docs
if (url.pathname === "/") {
return new Response(DOCS, {
status: 200,
headers: {
"content-type": "text/html",
},
});
}
const isDockerHub = upstream == registry_dockerHub;
const isQuay = upstream == registry_quay;
const authorization = request.headers.get("Authorization");

if (url.pathname.startsWith("/v1/")) {
let newUrl = url

// Docker API /v1/_ping
// https://docs.docker.com/reference/api/engine/version/v1.47/#tag/System/operation/SystemPing
if (url.pathname == "/v1/_ping") {
return new Response(null, {
status: 200,
headers: {
"content-type": "text/plain",
},
});
}

// Docker API /v1/search
if (url.pathname == "/v1/search") {
if(isDockerHub){
newUrl = new URL(index_dockerHub + "/v1/search");
}else if(isQuay){
newUrl = new URL(index_quay + "/v1/search");
}else{
newUrl = url
}

newUrl.search = url.search;
}

const headers = new Headers();
if (authorization) {
headers.set("Authorization", authorization);
}

// check if need to authenticate
const resp = await fetch(newUrl.toString(), {
method: "GET",
headers: headers,
redirect: "follow",
});

if (resp.status === 401) {
return responseUnauthorized(url);
}
return resp;
}

if (url.pathname == "/v2/") {
const newUrl = new URL(upstream + "/v2/");
const headers = new Headers();
Expand Down Expand Up @@ -89,10 +150,12 @@ async function handleRequest(request) {
}
return await fetchToken(wwwAuthenticate, scope, authorization);
}
console.log(JSON.stringify(url, null, 2))
// redirect for DockerHub library images
// Example: /v2/busybox/manifests/latest => /v2/library/busybox/manifests/latest
if (isDockerHub) {
const pathParts = url.pathname.split("/");
console.log(JSON.stringify(url, null, 2))
if (pathParts.length == 5) {
pathParts.splice(2, 0, "library");
const redirectUrl = new URL(url);
Expand Down Expand Up @@ -144,7 +207,7 @@ async function fetchToken(wwwAuthenticate, scope, authorization) {
}

function responseUnauthorized(url) {
const headers = new(Headers);
const headers = new Headers();
if (MODE == "debug") {
headers.set(
"Www-Authenticate",
Expand Down
5 changes: 5 additions & 0 deletions wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name = "cloudflare-docker-proxy"
compatibility_date = "2023-12-01"

[observability]
enabled = true
head_sampling_rate = 1 # optional. default = 1.

[dev]
ip = "0.0.0.0"
port = 8787
Expand All @@ -10,6 +14,7 @@ local_protocol = "http"
CUSTOM_DOMAIN = "libcuda.so"

[env.dev.vars]
CUSTOM_DOMAIN = "router.com"
MODE = "debug"
TARGET_UPSTREAM = "https://registry-1.docker.io"

Expand Down