不用公网 IP,也能用 Docker 跑通 Cloudflare Tunnel 教程
Cloudflare Docker部署教程|零基础可学
在日常建站、内网穿透、家庭服务器、NAS 服务暴露、Webhook 回调测试等场景中,我们经常会遇到一个问题:本地服务已经跑起来了,但外网无法访问。传统做法可能需要公网 IP、路由器端口映射、DDNS、反向代理、SSL 证书配置等,对新手并不友好。
Cloudflare 提供的 Cloudflare Tunnel 可以很好地解决这个问题。它可以让你的本地服务通过 Cloudflare 的网络安全地暴露到公网,而无需公网 IP,也不需要在路由器上开放端口。配合 Docker 部署后,整个过程更加简单、可维护,也方便迁移。
本文将以零基础视角,详细讲解如何使用 Docker 部署 Cloudflare Tunnel,让你可以把本地网站、NAS、面板服务等通过自己的域名安全访问。
一、Cloudflare Docker部署适合什么场景?
在开始之前,我们先明确一下本文要实现的目标。
假设你有一台服务器、家用电脑、NAS 或者树莓派,上面运行着一个本地服务,例如:
http://localhost:8080
或者局域网中的服务:
http://192.168.1.100:8080
你希望通过类似下面的域名访问它:
https://app.example.com
如果使用 Cloudflare Tunnel,就可以做到:
- 不需要公网 IP;
- 不需要路由器端口转发;
- 不需要手动申请 SSL 证书;
- 可以隐藏真实服务器 IP;
- 可以通过 Cloudflare 提供 HTTPS;
- Docker 部署简单,后期维护方便;
- 支持多个子域名转发到不同本地服务。
因此,Cloudflare Docker 部署非常适合以下用户:
- 家庭 NAS 用户;
- Home Assistant 用户;
- 自建博客用户;
- 本地开发测试用户;
- 需要公网 Webhook 回调的开发者;
- 不想开放服务器端口的个人站长;
- 想提升服务安全性的运维人员。
二、Cloudflare Tunnel是什么?
Cloudflare Tunnel 原名 Argo Tunnel,现在通常称为 Cloudflare Tunnel。它的核心组件是一个名为 cloudflared 的客户端程序。
它的工作方式可以简单理解为:
本地服务 → cloudflared 容器 → Cloudflare 网络 → 用户浏览器
传统暴露服务的方式是:
用户浏览器 → 公网 IP → 服务器开放端口 → 本地服务
而 Cloudflare Tunnel 的方式是:
本地服务主动连接 Cloudflare → Cloudflare 再把请求转发回来
这意味着你的服务器不需要开放入站端口,因为连接是由本地 cloudflared 主动发起到 Cloudflare 的。
这样做有几个明显好处:
- 服务器真实 IP 不容易暴露;
- 无需配置复杂的防火墙入站规则;
- 没有公网 IP 的家庭宽带也能使用;
- Cloudflare 可以帮你处理 HTTPS;
- 结合 Cloudflare Access 还可以做访问认证。
三、部署前准备工作
在正式部署之前,你需要准备以下内容。
1. 一个 Cloudflare 账号
你需要先注册 Cloudflare 账号。
官网地址:
https://www.cloudflare.com/
注册过程比较简单,使用邮箱即可完成。
2. 一个已经托管到 Cloudflare 的域名
Cloudflare Tunnel 通常需要配合域名使用。你需要有一个域名,并且已经将域名的 DNS 托管到 Cloudflare。
简单来说,你需要完成这几件事:
- 购买一个域名;
- 登录 Cloudflare;
- 添加该域名;
- 根据 Cloudflare 提示,到域名注册商处修改 Nameserver;
- 等待 Cloudflare 显示域名状态为 Active。
例如你的域名是:
example.com
后续我们可以创建子域名:
app.example.com
nas.example.com
home.example.com
分别指向不同的本地服务。
3. 一台可以运行 Docker 的机器
你需要有一台已经安装 Docker 的设备,例如:
- Linux 服务器;
- Ubuntu / Debian 主机;
- 群晖 NAS;
- unRAID;
- OpenWrt;
- 树莓派;
- Windows Docker Desktop;
- macOS Docker Desktop。
本文主要以 Linux 环境为例讲解。
你可以通过下面命令检查 Docker 是否安装成功:
docker -v
如果能看到类似输出,说明 Docker 已安装:
Docker version 26.1.4, build 5650f9b
同时建议安装 Docker Compose:
docker compose version
如果能正常显示版本号,说明可以使用 Compose 部署。
四、Cloudflare Tunnel部署方式说明
Cloudflare Tunnel 常见部署方式有两种:
方式一:通过 Token 快速部署
这种方式最简单,也是新手最推荐的方式。
优点:
- 不需要手动创建配置文件;
- 不需要管理证书文件;
- 直接复制 Cloudflare 提供的 Token;
- Docker 一行命令即可运行。
缺点:
- 配置主要在 Cloudflare 控制台中管理;
- 对于喜欢本地配置文件的用户来说不够直观。
方式二:通过配置文件部署
这种方式更适合进阶用户。
优点:
- 所有规则都可以写在本地 YAML 文件中;
- 适合 Git 管理;
- 灵活性更强。
缺点:
- 初次配置相对复杂;
- 需要登录授权并保存凭据;
- 对新手不如 Token 方式友好。
本文重点讲解 方式一:Token 快速部署,因为它最适合零基础用户。
五、创建 Cloudflare Tunnel
1. 登录 Cloudflare 控制台
打开 Cloudflare 后台:
https://dash.cloudflare.com/
登录你的账号。
2. 进入 Zero Trust 控制台
在左侧菜单或首页中找到:
Zero Trust
首次进入时,Cloudflare 可能会让你创建团队名称。按照提示创建即可。
例如团队名称可以填写:
myhome
创建完成后进入 Zero Trust 控制台。
3. 创建 Tunnel
在 Zero Trust 后台中,依次进入:
Networks → Tunnels
然后点击:
Create a tunnel
接着选择:
Cloudflared
然后点击下一步。
4. 填写 Tunnel 名称
你可以给 Tunnel 起一个容易识别的名字,例如:
home-server
或者:
nas-tunnel
名称仅用于后台识别,不影响访问域名。
填写后点击保存。
5. 选择 Docker 部署方式
Cloudflare 会要求你选择运行环境,例如:
- Docker;
- Linux;
- Windows;
- macOS;
- Kubernetes。
这里选择:
Docker
然后 Cloudflare 会生成一段类似下面的 Docker 命令:
docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token xxxxxxxxxxxxxxxxx
其中 --token 后面的长字符串就是你的 Tunnel Token。
注意:Token 相当于这个隧道的身份凭据,不要公开到网上,也不要提交到公开仓库。
六、使用 Docker Run 快速部署
如果你只是想快速运行,可以直接使用 Cloudflare 提供的命令。
示例:
docker run -d \
--name cloudflared \
--restart unless-stopped \
cloudflare/cloudflared:latest \
tunnel --no-autoupdate run --token 你的Token
参数解释如下:
| 参数 | 说明 |
|---|---|
-d |
后台运行容器 |
--name cloudflared |
容器名称 |
--restart unless-stopped |
容器异常退出后自动重启 |
cloudflare/cloudflared:latest |
使用官方 cloudflared 镜像 |
tunnel run |
运行 Tunnel |
--token |
使用 Cloudflare 提供的 Token 登录 |
运行后可以查看容器状态:
docker ps
如果看到 cloudflared 容器正在运行,说明第一步成功。
查看日志:
docker logs -f cloudflared
如果日志中出现类似内容:
Registered tunnel connection
说明 Tunnel 已经成功连接到 Cloudflare。
七、使用 Docker Compose部署Cloudflare Tunnel
虽然 docker run 很方便,但从长期维护角度来看,更推荐使用 Docker Compose。
1. 创建项目目录
例如:
mkdir -p /opt/cloudflared
cd /opt/cloudflared
2. 创建 docker-compose.yml
使用编辑器创建文件:
nano docker-compose.yml
写入以下内容:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token 你的Token
如果你使用的是较老版本 Docker Compose,也可以加上:
version: "3.8"
完整示例:
version: "3.8"
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token 你的Token
3. 启动容器
在 docker-compose.yml 所在目录执行:
docker compose up -d
查看运行状态:
docker compose ps
查看日志:
docker compose logs -f
如果日志中不断显示连接成功,说明 Tunnel 正常工作。
八、配置公网域名访问本地服务
Tunnel 创建好了,只是建立了 Cloudflare 与本地机器之间的连接。接下来需要配置访问规则,也就是告诉 Cloudflare:
当用户访问哪个域名时,要转发到本地哪个服务。
示例场景
假设你的本地有一个 Web 服务运行在:
http://localhost:8080
你希望通过下面的域名访问:
https://app.example.com
配置步骤
进入 Cloudflare Zero Trust 后台:
Networks → Tunnels
找到刚才创建的 Tunnel,点击进入配置。
找到:
Public Hostname
点击:
Add a public hostname
然后填写:
| 配置项 | 示例 |
|---|---|
| Subdomain | app |
| Domain | example.com |
| Path | 留空 |
| Type | HTTP |
| URL | localhost:8080 |
保存后,Cloudflare 会自动帮你创建对应 DNS 记录。
几分钟后访问:
https://app.example.com
如果你的本地服务正常运行,就可以看到页面。
九、Docker容器之间如何互通?
很多新手会遇到一个问题:
我的业务服务也是 Docker 容器,Cloudflared 容器里访问 localhost:8080 为什么不通?
这是因为在 Docker 中,每个容器都有自己的网络命名空间。对于 cloudflared 容器来说:
localhost
指的是 cloudflared 容器自己,而不是宿主机,也不是其他容器。
因此,如果你要让 Cloudflared 访问另一个 Docker 容器,推荐把它们放到同一个 Docker 网络中,然后通过容器名访问。
示例:同一个 Compose 中部署 Web 服务和 Cloudflared
假设你有一个 Nginx 服务,需要通过 Cloudflare Tunnel 暴露出去:
version: "3.8"
services:
web:
image: nginx:latest
container_name: my-nginx
restart: unless-stopped
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token 你的Token
然后在 Cloudflare 后台 Public Hostname 中填写:
http://web:80
注意这里不是:
http://localhost:80
而是使用服务名:
web
因为在同一个 Docker Compose 网络中,服务之间可以通过服务名互相访问。
示例:Cloudflared访问宿主机服务
如果你的服务运行在宿主机上,例如:
http://127.0.0.1:8080
那么在容器里直接访问 localhost:8080 通常是不通的。
在 Linux 上,你可以让容器使用 host 网络模式:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
network_mode: host
command: tunnel --no-autoupdate run --token 你的Token
然后 Public Hostname 中可以填写:
http://localhost:8080
不过需要注意,network_mode: host 在 Linux 上常用,在 Docker Desktop 的 macOS 和 Windows 环境中表现可能不同。
另一种方式是使用宿主机网关地址,例如:
http://host.docker.internal:8080
在部分 Linux 版本 Docker 中,你可能需要在 Compose 中加入:
extra_hosts:
- "host.docker.internal:host-gateway"
示例:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
command: tunnel --no-autoupdate run --token 你的Token
然后 Cloudflare 后台填写:
http://host.docker.internal:8080
十、同时暴露多个本地服务
Cloudflare Tunnel 可以同时转发多个域名到不同服务。
例如:
| 公网域名 | 本地地址 |
|---|---|
blog.example.com |
http://wordpress:80 |
nas.example.com |
http://192.168.1.10:5000 |
home.example.com |
http://homeassistant:8123 |
panel.example.com |
http://localhost:9000 |
在 Cloudflare 后台中,为同一个 Tunnel 添加多个 Public Hostname 即可。
例如:
博客服务
Subdomain: blog
Domain: example.com
Type: HTTP
URL: wordpress:80
NAS 管理页面
Subdomain: nas
Domain: example.com
Type: HTTP
URL: 192.168.1.10:5000
Home Assistant
Subdomain: home
Domain: example.com
Type: HTTP
URL: homeassistant:8123
配置保存后,每个域名都会通过同一个 Tunnel 转发到对应服务。
十一、HTTPS和证书需要自己配置吗?
一般情况下不需要。
当你使用 Cloudflare Tunnel 并通过 Cloudflare 托管的域名访问时,外部用户访问的是:
https://app.example.com
Cloudflare 会负责浏览器到 Cloudflare 边缘节点之间的 HTTPS 证书。
而 Cloudflare 到本地服务之间,可以使用 HTTP,也可以使用 HTTPS。
如果你的本地服务本身没有 HTTPS,配置时选择:
Type: HTTP
URL: localhost:8080
即可。
如果本地服务已经启用 HTTPS,可以选择:
Type: HTTPS
URL: localhost:8443
如果本地服务使用自签名证书,可能还需要在 Cloudflare Tunnel 的服务设置中开启跳过 TLS 验证,或者改用 HTTP 内网通信。
对于新手来说,最简单的方式是:
公网 HTTPS,内网 HTTP
也就是:
用户浏览器 --HTTPS--> Cloudflare --Tunnel--> 本地 HTTP 服务
这样既简单,又能保证公网访问时是 HTTPS。
十二、Cloudflare Tunnel安全建议
虽然 Cloudflare Tunnel 很方便,但不要因为方便就忽视安全。尤其是当你暴露的是管理面板、NAS、路由器后台、数据库面板等敏感服务时,一定要做好访问控制。
1. 不要直接暴露高风险后台
例如以下服务不建议直接裸奔到公网:
- NAS 管理后台;
- Portainer;
- 宝塔面板;
- Proxmox;
- OpenWrt;
- Home Assistant;
- 数据库管理工具;
- Jenkins;
- GitLab;
- 内网监控面板。
如果确实需要访问,建议配合 Cloudflare Access 做登录验证。
2. 启用 Cloudflare Access
Cloudflare Access 可以在用户访问你的服务之前,先要求进行身份验证。
例如你可以设置:
- 只有指定邮箱可以访问;
- 只有 Google 登录用户可以访问;
- 只有 GitHub 组织成员可以访问;
- 访问前需要一次性验证码。
这样即使别人知道你的域名,也无法直接进入服务页面。
配置入口通常在:
Zero Trust → Access → Applications
你可以添加一个 Self-hosted 应用,将域名设置为:
nas.example.com
然后设置访问策略,例如只允许你的邮箱:
yourname@example.com
3. 服务本身仍然要设置密码
Cloudflare Access 是第一层防护,但服务本身也应该设置强密码。
不要使用:
admin/admin
root/123456
test/test
建议使用:
- 长密码;
- 随机密码;
- 密码管理器;
- 双因素认证。
4. 不要泄露 Tunnel Token
Docker Compose 文件中如果写了 Token,不要上传到公开 GitHub 仓库。
如果你想更安全,可以使用 .env 文件管理 Token。
示例:
创建 .env:
TUNNEL_TOKEN=你的Token
docker-compose.yml 写成:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
这样后续管理更清晰,也更容易避免误提交。
十三、常见问题排查
1. 容器启动后访问域名显示 502
常见原因:
- 本地服务没有启动;
- Public Hostname 的 URL 填错;
- 容器网络不通;
- 把
localhost填错了; - 服务端口不正确。
排查方法:
查看 cloudflared 日志:
docker logs -f cloudflared
如果服务也是容器,确认它和 cloudflared 是否在同一个 Docker 网络中。
2. 日志显示连接成功,但域名打不开
可以检查:
- 域名是否已经托管到 Cloudflare;
- Public Hostname 是否保存成功;
- DNS 记录是否自动创建;
- 本地服务地址是否能在服务器上访问;
- 防火墙是否阻止了本地服务端口;
- Cloudflare Zero Trust 中 Tunnel 是否显示 Healthy。
3. Docker容器中访问 localhost 不通
这是最常见问题。
请记住:
容器里的 localhost = 容器自己
如果目标服务也是容器,请使用服务名:
http://web:80
如果目标服务在宿主机,请尝试:
http://host.docker.internal:端口
或者 Linux 下使用:
network_mode: host
4. 如何更新 cloudflared 镜像?
如果你使用的是 Docker Compose,可以这样更新:
cd /opt/cloudflared
docker compose pull
docker compose up -d
清理旧镜像:
docker image prune
由于命令中使用了:
--no-autoupdate
所以容器内部不会自动更新,需要通过 Docker 镜像更新。
5. 可以不用域名吗?
Cloudflare Tunnel 更推荐配合你自己的域名使用。
虽然 cloudflared 有临时隧道功能,可以生成临时域名,但不适合长期服务,也不适合生产环境。
如果你想长期稳定使用,建议购买一个域名并托管到 Cloudflare。
十四、推荐的目录结构
如果你后续会部署多个服务,建议使用清晰的目录结构:
/opt/
├── cloudflared/
│ ├── docker-compose.yml
│ └── .env
├── nginx/
│ └── docker-compose.yml
├── wordpress/
│ └── docker-compose.yml
└── homeassistant/
└── docker-compose.yml
也可以把 cloudflared 和业务服务放在同一个 Compose 项目中,便于网络互通。
对于零基础用户来说,建议先采用:
每个服务一个目录
等熟悉 Docker 网络后,再考虑统一编排。
十五、完整示例:部署一个Nginx并通过Cloudflare访问
下面给出一个完整示例,帮助你从零到一跑通。
1. 创建目录
mkdir -p /opt/demo-cloudflare
cd /opt/demo-cloudflare
2. 创建 docker-compose.yml
version: "3.8"
services:
web:
image: nginx:latest
container_name: demo-nginx
restart: unless-stopped
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token 你的Token
3. 启动服务
docker compose up -d
4. 配置 Public Hostname
在 Cloudflare Zero Trust 中添加:
Subdomain: demo
Domain: example.com
Type: HTTP
URL: web:80
5. 访问测试
打开浏览器访问:
https://demo.example.com
如果看到 Nginx 欢迎页面,说明部署成功。
十六、总结
通过本文,你应该已经掌握了使用 Docker 部署 Cloudflare Tunnel 的完整流程。
整体步骤可以概括为:
- 注册 Cloudflare 账号;
- 将域名托管到 Cloudflare;
- 安装 Docker 和 Docker Compose;
- 在 Zero Trust 中创建 Tunnel;
- 复制 Docker Token;
- 使用 Docker Compose 启动
cloudflared; - 添加 Public Hostname;
- 将域名转发到本地服务;
- 根据需要添加多个服务;
- 配合 Cloudflare Access 提升安全性。
对于零基础用户来说,最推荐的部署方案是:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token 你的Token
Cloudflare Tunnel 最大的优势在于:不需要公网 IP、不需要端口映射、不需要手动配置 HTTPS,就能把本地服务安全地发布到公网。
如果你只是想把一个本地网站、NAS 页面、Home Assistant、测试项目或个人服务开放给自己访问,那么 Cloudflare Tunnel + Docker 是非常值得学习和使用的方案。