diff --git a/src/help.html b/src/help.html new file mode 100644 index 000000000..9ea568c58 --- /dev/null +++ b/src/help.html @@ -0,0 +1,140 @@ + + + + + + 镜像使用说明 + + + + +
+

镜像使用说明

+ + GitHub + +
+
+
+

为了加速 Docker 镜像拉取,你可以使用以下命令设置 registry mirror:

+
sudo tee /etc/docker/daemon.json <<EOF
+{
+    "registry-mirrors": ["https://{{host}}"]
+}
+EOF
+# 配置完后需要重启 Docker 服务
+sudo systemctl restart docker
+
+

使用该代理从不同的镜像仓库拉取镜像,请参考以下命令:

+

+# 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 镜像
+
+

为了避免 Worker 用量耗尽,你可以手动 pull 镜像然后 re-tag 之后 push 至本地镜像仓库。

+
+
+ + + + \ No newline at end of file diff --git a/src/index.js b/src/index.js index a97a73819..e03bec47d 100644 --- a/src/index.js +++ b/src/index.js @@ -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", @@ -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) { @@ -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(); @@ -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); @@ -154,7 +217,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", diff --git a/wrangler.toml b/wrangler.toml index bbf4845d2..694ba7ecf 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -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 @@ -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" CUSTOM_DOMAIN = "exmaple.com"