mirror of
https://github.com/ciiiii/cloudflare-docker-proxy.git
synced 2025-12-06 14:42:51 +08:00
Compare commits
15 Commits
yscai/regi
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f0b9200de | ||
|
|
c7ca5c64f9 | ||
|
|
c595a14166 | ||
|
|
dfac79db55 | ||
|
|
e176bc4b29 | ||
|
|
47001590eb | ||
|
|
703fae4e63 | ||
|
|
24d7c9fc90 | ||
|
|
696009dd69 | ||
|
|
1bc56391bb | ||
|
|
aa61ad58cf | ||
|
|
d82c47d53a | ||
|
|
74b03d2aaf | ||
|
|
8df9982c2b | ||
|
|
d1d3bc252c |
4
.github/workflows/deploy.yaml
vendored
4
.github/workflows/deploy.yaml
vendored
@@ -16,8 +16,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Publish
|
- name: Publish
|
||||||
uses: cloudflare/wrangler-action@v3
|
uses: cloudflare/wrangler-action@v3
|
||||||
|
env:
|
||||||
|
CUSTOM_DOMAIN: ${{ secrets.CUSTOM_DOMAIN || 'libcuda.so' }}
|
||||||
with:
|
with:
|
||||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||||
accountId: ${{secrets.CF_ACCOUNT_ID}}
|
accountId: ${{secrets.CF_ACCOUNT_ID}}
|
||||||
|
vars:
|
||||||
|
CUSTOM_DOMAIN
|
||||||
command: deploy --env production --minify src/index.js
|
command: deploy --env production --minify src/index.js
|
||||||
environment: production
|
environment: production
|
||||||
23
.github/workflows/stage.yaml
vendored
23
.github/workflows/stage.yaml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: Deploy to Cloudflare Workers(Staging)
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
repository_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Build & Deploy
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Publish
|
|
||||||
uses: cloudflare/wrangler-action@v3
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
|
||||||
accountId: ${{secrets.CF_ACCOUNT_ID}}
|
|
||||||
command: deploy --env staging --minify src/index.js
|
|
||||||
environment: staging
|
|
||||||
17
README.md
17
README.md
@@ -1,5 +1,14 @@
|
|||||||
# cloudflare-docker-proxy
|
# cloudflare-docker-proxy
|
||||||
|
|
||||||
|
> ### ⚠️ **Important Notice**
|
||||||
|
> <span style="color:#d73a49;font-weight:bold">Docker Hub is rate-limiting Cloudflare Worker IPs, causing frequent <code>429</code> errors.</span>
|
||||||
|
> <span style="color:#d73a49;font-weight:bold">This project is currently NOT recommended for production use.</span>
|
||||||
|
|
||||||
|
|
||||||
|
Due to the current instability, this project is not recommended for production use.
|
||||||
|
We will provide updates as soon as more information becomes available.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[](https://deploy.workers.cloudflare.com/?url=https://github.com/ciiiii/cloudflare-docker-proxy)
|
[](https://deploy.workers.cloudflare.com/?url=https://github.com/ciiiii/cloudflare-docker-proxy)
|
||||||
@@ -8,13 +17,13 @@
|
|||||||
|
|
||||||
## Deploy
|
## Deploy
|
||||||
|
|
||||||
1. fork this project
|
1. click the "Deploy With Workers" button
|
||||||
2. modify the link of the above button to your fork url
|
2. follow the instructions to fork and deploy
|
||||||
3. click the button, you will be redirected to the deploy page
|
3. update routes as you requirement
|
||||||
|
|
||||||
[](https://deploy.workers.cloudflare.com/?url=https://github.com/ciiiii/cloudflare-docker-proxy)
|
[](https://deploy.workers.cloudflare.com/?url=https://github.com/ciiiii/cloudflare-docker-proxy)
|
||||||
|
|
||||||
## Config tutorial
|
## Routes configuration tutorial
|
||||||
|
|
||||||
1. use cloudflare worker host: only support proxy one registry
|
1. use cloudflare worker host: only support proxy one registry
|
||||||
```javascript
|
```javascript
|
||||||
|
|||||||
3023
package-lock.json
generated
Normal file
3023
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier --write '**/*.{js,css,json,md}'",
|
"format": "prettier --write '**/*.{js,css,json,md}'",
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"dev": "wrangler dev src/index.js --env dev"
|
"dev": "npx wrangler dev src/index.js --env dev"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "src/index.js"
|
"main": "src/index.js"
|
||||||
|
|||||||
78
src/index.js
78
src/index.js
@@ -7,16 +7,17 @@ const dockerHub = "https://registry-1.docker.io";
|
|||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
// production
|
// production
|
||||||
"docker.libcuda.so": dockerHub,
|
["docker." + CUSTOM_DOMAIN]: dockerHub,
|
||||||
"quay.libcuda.so": "https://quay.io",
|
["quay." + CUSTOM_DOMAIN]: "https://quay.io",
|
||||||
"gcr.libcuda.so": "https://gcr.io",
|
["gcr." + CUSTOM_DOMAIN]: "https://gcr.io",
|
||||||
"k8s-gcr.libcuda.so": "https://k8s.gcr.io",
|
["k8s-gcr." + CUSTOM_DOMAIN]: "https://k8s.gcr.io",
|
||||||
"k8s.libcuda.so": "https://registry.k8s.io",
|
["k8s." + CUSTOM_DOMAIN]: "https://registry.k8s.io",
|
||||||
"ghcr.libcuda.so": "https://ghcr.io",
|
["ghcr." + CUSTOM_DOMAIN]: "https://ghcr.io",
|
||||||
"cloudsmith.libcuda.so": "https://docker.cloudsmith.io",
|
["cloudsmith." + CUSTOM_DOMAIN]: "https://docker.cloudsmith.io",
|
||||||
|
["ecr." + CUSTOM_DOMAIN]: "https://public.ecr.aws",
|
||||||
|
|
||||||
// staging
|
// staging
|
||||||
"docker-staging.libcuda.so": dockerHub,
|
["docker-staging." + CUSTOM_DOMAIN]: dockerHub,
|
||||||
};
|
};
|
||||||
|
|
||||||
function routeByHosts(host) {
|
function routeByHosts(host) {
|
||||||
@@ -31,6 +32,9 @@ function routeByHosts(host) {
|
|||||||
|
|
||||||
async function handleRequest(request) {
|
async function handleRequest(request) {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
|
if (url.pathname == "/") {
|
||||||
|
return Response.redirect(url.protocol + "//" + url.host + "/v2/", 301);
|
||||||
|
}
|
||||||
const upstream = routeByHosts(url.hostname);
|
const upstream = routeByHosts(url.hostname);
|
||||||
if (upstream === "") {
|
if (upstream === "") {
|
||||||
return new Response(
|
return new Response(
|
||||||
@@ -57,24 +61,9 @@ async function handleRequest(request) {
|
|||||||
redirect: "follow",
|
redirect: "follow",
|
||||||
});
|
});
|
||||||
if (resp.status === 401) {
|
if (resp.status === 401) {
|
||||||
if (MODE == "debug") {
|
return responseUnauthorized(url);
|
||||||
headers.set(
|
|
||||||
"Www-Authenticate",
|
|
||||||
`Bearer realm="http://${url.host}/v2/auth",service="cloudflare-docker-proxy"`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
headers.set(
|
|
||||||
"Www-Authenticate",
|
|
||||||
`Bearer realm="https://${url.hostname}/v2/auth",service="cloudflare-docker-proxy"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new Response(JSON.stringify({ message: "UNAUTHORIZED" }), {
|
|
||||||
status: 401,
|
|
||||||
headers: headers,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return resp;
|
|
||||||
}
|
}
|
||||||
|
return resp;
|
||||||
}
|
}
|
||||||
// get token
|
// get token
|
||||||
if (url.pathname == "/v2/auth") {
|
if (url.pathname == "/v2/auth") {
|
||||||
@@ -119,9 +108,23 @@ async function handleRequest(request) {
|
|||||||
const newReq = new Request(newUrl, {
|
const newReq = new Request(newUrl, {
|
||||||
method: request.method,
|
method: request.method,
|
||||||
headers: request.headers,
|
headers: request.headers,
|
||||||
redirect: "follow",
|
// don't follow redirect to dockerhub blob upstream
|
||||||
|
redirect: isDockerHub ? "manual" : "follow",
|
||||||
});
|
});
|
||||||
return await fetch(newReq);
|
const resp = await fetch(newReq);
|
||||||
|
if (resp.status == 401) {
|
||||||
|
return responseUnauthorized(url);
|
||||||
|
}
|
||||||
|
// handle dockerhub blob redirect manually
|
||||||
|
if (isDockerHub && resp.status == 307) {
|
||||||
|
const location = new URL(resp.headers.get("Location"));
|
||||||
|
const redirectResp = await fetch(location.toString(), {
|
||||||
|
method: "GET",
|
||||||
|
redirect: "follow",
|
||||||
|
});
|
||||||
|
return redirectResp;
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAuthenticate(authenticateStr) {
|
function parseAuthenticate(authenticateStr) {
|
||||||
@@ -146,9 +149,28 @@ async function fetchToken(wwwAuthenticate, scope, authorization) {
|
|||||||
if (scope) {
|
if (scope) {
|
||||||
url.searchParams.set("scope", scope);
|
url.searchParams.set("scope", scope);
|
||||||
}
|
}
|
||||||
headers = new Headers();
|
const headers = new Headers();
|
||||||
if (authorization) {
|
if (authorization) {
|
||||||
headers.set("Authorization", authorization);
|
headers.set("Authorization", authorization);
|
||||||
}
|
}
|
||||||
return await fetch(url, { method: "GET", headers: headers });
|
return await fetch(url, { method: "GET", headers: headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function responseUnauthorized(url) {
|
||||||
|
const headers = new Headers();
|
||||||
|
if (MODE == "debug") {
|
||||||
|
headers.set(
|
||||||
|
"Www-Authenticate",
|
||||||
|
`Bearer realm="http://${url.host}/v2/auth",service="cloudflare-docker-proxy"`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
headers.set(
|
||||||
|
"Www-Authenticate",
|
||||||
|
`Bearer realm="https://${url.hostname}/v2/auth",service="cloudflare-docker-proxy"`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Response(JSON.stringify({ message: "UNAUTHORIZED" }), {
|
||||||
|
status: 401,
|
||||||
|
headers: headers,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,21 +6,25 @@ ip = "0.0.0.0"
|
|||||||
port = 8787
|
port = 8787
|
||||||
local_protocol = "http"
|
local_protocol = "http"
|
||||||
|
|
||||||
|
[env.vars]
|
||||||
|
CUSTOM_DOMAIN = "libcuda.so"
|
||||||
|
|
||||||
[env.dev.vars]
|
[env.dev.vars]
|
||||||
MODE = "debug"
|
MODE = "debug"
|
||||||
TARGET_UPSTREAM = "https://registry-1.docker.io"
|
TARGET_UPSTREAM = "https://registry-1.docker.io"
|
||||||
|
CUSTOM_DOMAIN = "exmaple.com"
|
||||||
|
|
||||||
[env.production]
|
[env.production]
|
||||||
name = "cloudflare-docker-proxy"
|
name = "cloudflare-docker-proxy"
|
||||||
routes = [
|
# routes = [
|
||||||
{ pattern = "docker.libcuda.so", custom_domain = true },
|
# { pattern = "docker.libcuda.so", custom_domain = true },
|
||||||
{ pattern = "quey.libcuda.so", custom_domain = true },
|
# { pattern = "quay.libcuda.so", custom_domain = true },
|
||||||
{ pattern = "gcr.libcuda.so", custom_domain = true },
|
# { pattern = "gcr.libcuda.so", custom_domain = true },
|
||||||
{ pattern = "k8s-gcr.libcuda.so", custom_domain = true },
|
# { pattern = "k8s-gcr.libcuda.so", custom_domain = true },
|
||||||
{ pattern = "k8s.libcuda.so", custom_domain = true },
|
# { pattern = "k8s.libcuda.so", custom_domain = true },
|
||||||
{ pattern = "ghcr.libcuda.so", custom_domain = true },
|
# { pattern = "ghcr.libcuda.so", custom_domain = true },
|
||||||
{ pattern = "cloudsmith.libcuda.so", custom_domain = true },
|
# { pattern = "cloudsmith.libcuda.so", custom_domain = true },
|
||||||
]
|
# ]
|
||||||
|
|
||||||
[env.production.vars]
|
[env.production.vars]
|
||||||
MODE = "production"
|
MODE = "production"
|
||||||
@@ -28,7 +32,7 @@ TARGET_UPSTREAM = ""
|
|||||||
|
|
||||||
[env.staging]
|
[env.staging]
|
||||||
name = "cloudflare-docker-proxy-staging"
|
name = "cloudflare-docker-proxy-staging"
|
||||||
route = { pattern = "docker-staging.libcuda.so", custom_domain = true }
|
# route = { pattern = "docker-staging.libcuda.so", custom_domain = true }
|
||||||
|
|
||||||
[env.staging.vars]
|
[env.staging.vars]
|
||||||
MODE = "staging"
|
MODE = "staging"
|
||||||
|
|||||||
Reference in New Issue
Block a user