Cloudflare 多环境部署指南

概述

本文档说明如何在 Docker 中配置和运行开发版、生产版的 Cloudflare Tunnel,实现:

  • 本地版:本地开发环境(localhost)
  • 开发版:团队协作测试环境(dev.hi-maker.com)
  • 生产版:正式生产环境(mbe.hi-maker.com)

架构图

┌─────────────────────────────────────────────────────────┐
│                    公网访问                              │
│  dev.hi-maker.com  │  mbe.hi-maker.com                  │
└────────────────────┬────────────────────────────────────┘
                     │
         ┌───────────┴───────────┐
         │  Cloudflare Tunnel   │
         │  (加密隧道)           │
         └───────────┬───────────┘
                     │
    ┌────────────────┴────────────────┐
    │                                │
┌───▼──────────┐            ┌───────▼────────┐
│  开发版       │            │   生产版        │
│              │            │                │
│ mbe-api-dev  │            │ mbe-api        │
│ (8001)       │            │ (8000)         │
│              │            │                │
│ mbe-tunnel-dev│           │ mbe-cloudflared│
│              │            │                │
└──────────────┘            └────────────────┘

当前状态

Docker 容器状态

容器名 状态 用途 Tunnel 域名
mbe-tunnel-dev ✅ 运行中 开发版 Tunnel mises-engine-dev dev.hi-maker.com
mbe-cloudflared ⚠️ 连接问题 生产版 Tunnel mbe-prod mbe.hi-maker.com
mbe-api-dev ✅ 运行中 开发版 API - localhost:8001

Cloudflare Dashboard 状态

Tunnel 名称 状态 用途 域名
mises-engine-dev ⚠️ 连接不稳定 开发版 dev.hi-maker.com
mbe-prod ❌ DOWN 生产版 mbe.hi-maker.com

配置步骤

1. 环境变量配置

.env 文件中配置两个 Tunnel Token:

# 开发版 Tunnel Token
CLOUDFLARE_TUNNEL_TOKEN_DEV=eyJhIjoi...

# 生产版 Tunnel Token
CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoi...

2. Docker Compose 配置

开发版 Tunnel (docker-compose.dev.cloudflare.yml)

version: "3.9"

services:
  cloudflared-dev:
    image: cloudflare/cloudflared:latest
    container_name: mbe-tunnel-dev
    restart: unless-stopped
    command: >
      tunnel run
      --protocol http2
      --loglevel info
    environment:
      - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN_DEV}
    networks:
      - mbe-dev-network
    depends_on:
      - mbe-api-dev
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    # 网络优化配置
    extra_hosts:
      - "host.docker.internal:host-gateway"

networks:
  mbe-dev-network:
    name: mbe-dev-network
    external: false

生产版 Tunnel (docker-compose.cloudflare.yml)

version: "3.9"

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: mbe-cloudflared
    restart: unless-stopped
    command: >
      tunnel run
      --protocol http2
      --loglevel info
    environment:
      - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
    networks:
      - default
    depends_on:
      - mbe-api
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

networks:
  default:
    name: mbe-monorepo_default
    external: true

3. Cloudflare Dashboard 配置

开发版 Tunnel (mises-engine-dev)

  1. 访问:https://one.dash.cloudflare.com/
  2. 进入:Networks > Tunnels > mises-engine-dev
  3. 配置 Public Hostname
    • Subdomain: dev
    • Domain: hi-maker.com
    • Service Type: HTTP
    • URL: http://mbe-api-dev:8000(使用容器名)

生产版 Tunnel (mbe-prod)

  1. 进入:Networks > Tunnels > mbe-prod
  2. 配置 Public Hostname
    • Subdomain: mbe
    • Domain: hi-maker.com
    • Service Type: HTTP
    • URL: http://mbe-api:8000(使用容器名)

启动和停止

启动开发版

# 启动开发版服务
docker compose -f docker-compose.dev.yml up -d

# 启动开发版 Tunnel
docker compose -f docker-compose.dev.cloudflare.yml up -d

启动生产版

# 启动生产版服务
docker compose -f docker-compose.yml up -d

# 启动生产版 Tunnel
docker compose -f docker-compose.cloudflare.yml up -d

同时运行两个环境

两个环境使用独立的网络和端口,可以同时运行:

# 启动所有服务
docker compose -f docker-compose.dev.yml -f docker-compose.dev.cloudflare.yml up -d
docker compose -f docker-compose.yml -f docker-compose.cloudflare.yml up -d

# 查看状态
docker ps --filter "name=mbe"

解决网络连接问题

问题现象

日志中出现:

ERR failed to dial to edge with quic: timeout: no recent network activity
ERR TLS handshake with edge error: EOF
ERR there are no free edge addresses left to resolve to

解决方案

方案 1:使用 HTTP/2 协议(推荐)

修改 command 参数,强制使用 HTTP/2:

command: >
  tunnel run
  --protocol http2
  --loglevel info

HTTP/2 比 QUIC 更稳定,在国内网络环境下连接成功率更高。

方案 2:配置代理(如果方案1无效)

如果您的网络环境需要代理访问 Cloudflare:

environment:
  - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
  - HTTP_PROXY=http://proxy.example.com:8080
  - HTTPS_PROXY=http://proxy.example.com:8080
  - NO_PROXY=localhost,127.0.0.1

方案 3:增加重试和超时配置

创建配置文件 deploy/cloudflared/config.yml

tunnel: <TUNNEL_ID>
credentials-file: /root/.cloudflared/<TUNNEL_ID>.json

# 网络优化
protocol: http2
retries: 10
grace-period: 30s

# 连接超时配置
originRequest:
  connectTimeout: 30s
  tcpKeepAlive: 15s
  keepAliveConnections: 100
  keepAliveTimeout: 90s
  noHappyEyeballs: false

ingress:
  - hostname: dev.hi-maker.com
    service: http://mbe-api-dev:8000
  - service: http_status:404

然后在 docker-compose 中使用配置文件:

volumes:
  - ./deploy/cloudflared/config.yml:/etc/cloudflared/config.yml:ro
command: tunnel --config /etc/cloudflared/config.yml run

方案 4:使用 Cloudflare WARP(最佳方案)

如果以上方案都无效,可以考虑使用 Cloudflare WARP 客户端:

  1. 安装 WARP 客户端:https://1.1.1.1/
  2. 启用 WARP 连接
  3. Docker 容器会自动使用 WARP 网络

开发工作流

1. 本地开发

# 启动本地开发环境(不使用 Tunnel)
docker compose -f docker-compose.dev.yml up -d

# 访问:http://localhost:8001

2. 部署到开发版(团队测试)

# 确保开发版服务运行
docker compose -f docker-compose.dev.yml up -d

# 启动开发版 Tunnel
docker compose -f docker-compose.dev.cloudflare.yml up -d

# 团队访问:https://dev.hi-maker.com

3. 部署到生产版

# 确保生产版服务运行
docker compose -f docker-compose.yml up -d

# 启动生产版 Tunnel
docker compose -f docker-compose.cloudflare.yml up -d

# 用户访问:https://mbe.hi-maker.com

验证和监控

检查 Tunnel 状态

# 查看开发版 Tunnel 日志
docker logs mbe-tunnel-dev --tail 50

# 查看生产版 Tunnel 日志
docker logs mbe-cloudflared --tail 50

检查 Cloudflare Dashboard

  1. 访问:https://one.dash.cloudflare.com/
  2. 进入:Networks > Tunnels
  3. 查看 Tunnel 状态应为 HEALTHY

测试访问

# 测试开发版
curl https://dev.hi-maker.com/api/health

# 测试生产版
curl https://mbe.hi-maker.com/api/health

常见问题

Q1: Tunnel 连接失败

检查:

  1. Token 是否正确
  2. 服务是否运行(docker ps
  3. Cloudflare Dashboard 中的 Service URL 是否正确

解决:

# 重启 Tunnel
docker restart mbe-tunnel-dev
docker restart mbe-cloudflared

# 查看日志
docker logs mbe-tunnel-dev --tail 50

Q2: 502 Bad Gateway

原因: 后端服务未运行或 Service URL 配置错误

解决:

# 检查服务状态
docker ps --filter "name=mbe-api"

# 检查 Cloudflare Dashboard 中的 Service URL
# 应该使用容器名:http://mbe-api-dev:8000

Q3: 网络连接超时

原因: 国内网络访问 Cloudflare 边缘节点困难

解决:

  1. 使用 --protocol http2(已在配置中)
  2. 配置代理(如果需要)
  3. 使用 Cloudflare WARP 客户端

最佳实践

  1. 开发版用于团队协作测试

    • 频繁更新和测试
    • 允许不稳定状态
  2. 生产版保持稳定

    • 只在测试通过后部署
    • 监控连接状态
  3. 使用独立的 Token

    • 开发版和生产版使用不同的 Token
    • 便于独立管理和监控
  4. 定期检查日志

    • 每天检查 Tunnel 日志
    • 及时发现和解决问题
  5. 备份配置

    • 保存 Token 到安全位置
    • 记录 Cloudflare Dashboard 配置

总结

通过以上配置,您可以:

  • ✅ 在本地开发(localhost)
  • ✅ 部署到开发版供团队测试(dev.hi-maker.com)
  • ✅ 部署到生产版供用户访问(mbe.hi-maker.com)
  • ✅ 同时运行多个环境,互不影响
  • ✅ 解决网络连接问题,提高稳定性