
### **利用Cloudflare Workers轻松搭建免费Docker Hub镜像加速器**
#### **前言:为什么要自建加速器?**
对于许多开发者来说,直接从 Docker Hub 拉取镜像时常会遇到速度缓慢甚至连接失败的问题。这严重影响了开发和部署效率。虽然存在一些公共的镜像加速服务,但它们可能不稳定或存在安全隐患。
本教程将指导您如何利用 Cloudflare 强大且免费的 Workers 服务,搭建一个属于您自己的、稳定高效的 Docker Hub 镜像加速器。整个过程无需服务器,只需一个域名,即可享受 Cloudflare 全球CDN网络带来的极速体验。
**核心优势:**
* **完全免费**:Cloudflare Workers 的免费套餐提供每日10万次请求,对于个人或小型团队的日常使用綽綽有餘。
* **性能卓越**:借助 Cloudflare 的全球分布式网络,您的 Docker 拉取请求将被路由到最近的节点,大大提升下载速度。
* **无需维护**:基于 Serverless 架构,您无需关心服务器的购买、配置和运维。
* **高安全性**:所有流量均通过您自己的 Cloudflare 账户,安全可控。
#### **准备工作**
在开始之前,请确保您已准备好以下两项:
1. **一个 Cloudflare 账户**:如果还没有,可以前往 [Cloudflare官网](https://dash.cloudflare.com/) 免费注册。
2. **一个您自己的域名**:您可以在任何域名注册商处购买。推荐使用价格便宜的 `.xyz`、`.top` 等域名。购买后,需要将该域名的 DNS 管理权交由 Cloudflare。
> **如何将域名交给 Cloudflare 管理?**
> 1. 登录 Cloudflare,点击“添加站点”。
> 2. 输入您购买的域名,选择免费计划。
> 3. Cloudflare 会扫描您现有的 DNS 记录,并提供两个 Cloudflare 的**名称服务器 (Nameserver)**地址。
> 4. 回到您购买域名的平台(如GoDaddy、NameSilo等),找到 DNS 设置,将默认的名称服务器更改为 Cloudflare 提供的那两个。
> 5. 等待几分钟到几小时,DNS 全球生效后,您的域名就成功由 Cloudflare 解析和管理了。
---
### **详细搭建步骤**
#### **第一步:创建 Cloudflare Worker**
1. 登录到您的 [Cloudflare 仪表盘](https://dash.cloudflare.com/)。
2. 在左侧导航栏中,找到并点击 **Workers 和 Pages**。
3. 点击 **创建应用程序** > **创建 Worker**。
4. 为您的 Worker 指定一个易于记忆的名称,例如 `docker-mirror`。这个名称将成为 Worker 的初始子域名的一部分(如 `docker-mirror.your-worker-name.workers.dev`)。
5. 点击 **部署**。一个包含默认代码的 Worker 就创建并部署成功了。
#### **第二步:配置 Worker 核心代码**
接下来,我们需要将默认代码替换为我们的代理逻辑代码。
1. 在 Worker 的管理界面,点击 **编辑代码** 按钮。
2. 您会看到一个在线代码编辑器,其中有一个 `index.js` 或 `_worker.js` 文件。**删除其中的所有默认代码**,然后将下面的代码完整地复制粘贴进去。
**`_worker.js` 代码:**
```javascript
/**
* Docker Hub a reverse proxy for Cloudflare Workers
*
* @author BiliBili-jz
* @see https://github.com/BiliBili-jz/docker-hub-mirror
*
* Please check the latest version of the worker script from the above address
* and deploy it to your Cloudflare account.
*/
// 镜像仓库地址
const hub_host = 'registry-1.docker.io'
// 自定义脚本(如果不需要可以设置为 "" 或 null)
// 例如,您可以创建一个 Gist 或其他静态文本服务来存放一个 shell 脚本,
// 用户通过 `curl -fsSL your-domain.com | sh` 即可自动配置 Docker。
const custom_script = "https://gist.githubusercontent.com/BiliBili-jz/345424747a9e6a048701a2d16918d363/raw/install.sh"
export default {
async fetch(request, env, ctx) {
let url = new URL(request.url)
const path = url.pathname
// 处理根路径或特定路径的请求,提供使用说明
if (path === '/' || path.startsWith('/v2/')) {
// 如果是 v2 API 路径,则进行代理
if (path.startsWith('/v2/')) {
return proxyToDockerHub(request, path)
}
// 否则,提供一个友好的使用说明页面
const worker_domain = url.hostname
const html = await generateUsagePage(worker_domain)
return new Response(html, {
status: 200,
headers: {
'Content-Type': 'text/html; charset=utf-8',
},
})
}
// 处理自定义安装脚本
else if (custom_script && (path === '/install' || path === '/install.sh')) {
return fetch(custom_script)
}
// 其他所有未知路径返回 404
else {
return new Response('Not Found', { status: 404 })
}
},
}
/**
* 代理请求到 Docker Hub
* @param {Request} request 原始请求
* @param {string} path 请求路径
* @returns {Promise
}
*/
async function proxyToDockerHub(request, path) {
const registry_url = new URL(path, 'https://' + hub_host)
const new_headers = new Headers(request.headers)
new_headers.set('Host', hub_host)
// 创建一个新的请求以转发到 Docker Hub
const proxy_request = new Request(registry_url, {
method: request.method,
headers: new_headers,
body: request.body,
redirect: 'follow', // 遵循重定向
})
// 发起请求
const response = await fetch(proxy_request)
// 处理响应头,特别是针对认证的 WWW-Authenticate 头
if (path === '/v2/' && response.status === 401) {
const new_response_headers = new Headers(response.headers)
const auth_header = new_response_headers.get('WWW-Authenticate')
// 重写认证域名,确保客户端能正确回调到我们的 Worker
if (auth_header) {
const new_auth_header = auth_header.replace(
'auth.docker.io',
new URL(request.url).hostname
)
new_response_headers.set('WWW-Authenticate', new_auth_header)
}
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: new_response_headers,
})
}
// 对于 Docker OAuth 认证回调的特殊处理
else if (
path.startsWith('/v2/auth') ||
path.startsWith('/token') ||
path.startsWith('/v2/token')
) {
const auth_url_obj = new URL(request.url)
const service = auth_url_obj.searchParams.get('service')
const scope = auth_url_obj.searchParams.get('scope')
// 将请求转发到正确的 Docker 认证服务
return fetch(`https://auth.docker.io/token?service=${service}&scope=${scope}`)
}
return response
}
/**
* 生成一个美观且信息丰富的使用说明页面
* @param {string} host Worker 的域名
* @returns {string} HTML 字符串
*/
async function generateUsagePage(host) {
// 动态生成使用说明,避免硬编码
return `
Docker 镜像加速服务
Docker 镜像加速服务已就绪
此服务由 Cloudflare Workers 强力驱动,旨在为您提供更快速、更稳定的 Docker 镜像拉取体验。
配置 Docker 加速器
请创建或修改 /etc/docker/daemon.json
文件(如果文件不存在,请新建),并加入以下内容。请务必将 ${host}
替换为您自己的加速域名。
{
"registry-mirrors": ["https://${host}"]
}
修改配置后,请不要忘记重启 Docker 服务以使配置生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
手动拉取镜像示例
如果您不想修改全局配置,也可以在拉取镜像时手动指定加速地址:
# 拉取官方的 Ubuntu 镜像
docker pull ${host}/library/ubuntu:latest
# 拉取 k8s 使用的 coredns 镜像
docker pull ${host}/coredns/coredns:latest
# 拉取后可以重新打标签为原始名称
docker tag ${host}/library/ubuntu:latest ubuntu:latest
`
}
```
3. 粘贴完代码后,点击右上角的 **保存并部署** 按钮。您的 Worker 代理服务现在已经启动并运行了!
#### **第三步:绑定自定义域名**
直接使用 `workers.dev` 的子域名也可以,但它较长且不便于记忆。绑定到您自己的域名下是更好的选择。
1. 返回到 `docker-mirror` Worker 的管理页面,选择 **触发器 (Triggers)** 标签页。
2. 在“自定义域”部分,点击 **添加自定义域**。
3. 输入一个您想用于加速服务的子域名,例如 `docker.yourdomain.com` (请将 `yourdomain.com` 替换为您自己的域名)。
4. 点击 **添加**。Cloudflare 会自动为您处理 SSL 证书和 DNS 解析记录,稍等片刻即可生效。
至此,您的专属 Docker 镜像加速器已全部搭建完成!它的访问地址就是您刚刚绑定的 `https://docker.yourdomain.com`。
---
### **如何使用您的加速服务**
现在,您可以将 Docker 客户端配置为使用这个新的加速地址了。
#### **方法一:全局配置(推荐)**
这是最方便的方法,一次配置,永久生效。
1. 打开终端,编辑 Docker 的配置文件 `daemon.json`。在 Linux 系统上,它通常位于 `/etc/docker/daemon.json`。
```bash
sudo nano /etc/docker/daemon.json
```
2. 将以下内容复制进去。**注意:** 请将 `docker.yourdomain.com` 替换为您上一步绑定的真实域名!
```json
{
"registry-mirrors": ["https://docker.yourdomain.com"]
}
```
> 如果该文件已有内容,请确保 `registry-mirrors` 是一个 JSON 数组,并将您的域名添加进去。
3. 保存文件并退出编辑器。
4. 重启 Docker 服务以应用新的配置。
```bash
sudo systemctl daemon-reload
sudo systemctl restart docker
```
5. 可以通过 `docker info` 命令来验证加速器是否配置成功。在输出的信息中,查找 "Registry Mirrors" 部分,如果能看到您的域名,就说明配置成功了。
#### **方法二:手动拉取指定镜像**
如果您只是临时需要加速某个镜像,或者不想修改全局配置,可以采用手动指定的方式。
语法是在镜像名称前加上您的加速域名和斜杠。
```bash
# 通过加速器拉取官方的 Nginx 镜像
docker pull docker.yourdomain.com/library/nginx:latest
# 拉取后,您可以为其重新打上一个简短的标签,方便使用
docker tag docker.yourdomain.com/library/nginx:latest nginx:latest
```
### **总结与提醒**
通过以上步骤,您已经成功地为自己构建了一个私有、免费且高效的 Docker Hub 镜像加速器。这不仅解决了网络访问问题,还让您对整个流程有了更深入的理解。
* **注意用量**:请留意 Cloudflare 的免费套餐限制(每日10万次请求)。对于个人使用来说是完全足够的,但请避免公开分享您的加速地址,以免额度被耗尽。
* **访问验证**:您可以直接在浏览器中访问您的加速域名(例如 `https://docker.yourdomain.com`),如果看到美观的使用说明页面,说明 Worker 部署成功。
祝您编码愉快!
0 评论