Fly.io:边缘计算应用托管的全面解析

NOTE

本文档最后更新于 2026年4月,深入剖析 Fly.io 的边缘计算架构、多区域部署策略、持久化存储方案,以及与 Cloudflare Workers 的对比分析。


目录

  1. 概述与技术架构
  2. 核心概念解析
  3. Fly Volumes 持久存储
  4. Fly Machines 微虚拟机
  5. 多区域部署策略
  6. 价格模型详解
  7. 与 Cloudflare Workers 对比
  8. 实战部署指南
  9. 选型建议

概述与技术架构

什么是 Fly.io

Fly.io 是一个专注于边缘计算的应用托管平台,允许开发者将应用部署到全球多个数据中心,实现低延迟、高可用的服务。与传统云服务不同,Fly.io 的核心理念是将应用逻辑推送到离用户最近的位置,而非让用户连接到遥远的中心化服务器。

Fly.io 支持多种应用类型:

  • Web 应用:Node.js、Python、Ruby、Go、Rust 等
  • 容器化应用:Docker 镜像
  • 静态站点:配合 Flyctl CDN
  • 长连接应用:WebSocket、gRPC、游戏服务器

技术架构

Fly.io 的底层架构融合了两种核心技术:

组件技术作用
全球负载均衡Anycast就近路由、健康检查
网络隧道WireGuard安全通信、加密传输
计算资源Firecracker VMs轻量级虚拟机隔离
持久存储NVMe SSD高性能本地存储

Anycast 路由机制

用户请求 → 最近数据中心(通过 Anycast)
                    ↓
            Fly Proxy(边缘代理)
                    ↓
        ┌───────────┴───────────┐
        ↓                       ↓
    Fly Machine            Fly Machine
    (香港)                  (新加坡)
        ↓                       ↓
    Fly Volume             Fly Volume
    (本地存储)              (本地存储)

Anycast 确保用户请求自动路由到物理距离最近的数据中心,无需手动配置区域选择。

WireGuard 网络隧道

Fly.io 使用 WireGuard 构建全球私有网络:

# WireGuard 配置示例(自动生成)
[Interface]
PrivateKey = <auto-generated>
Address = 10.0.0.2/16
MTU = 1420
 
[Peer]
PublicKey = <fly-proxy-pubkey>
Endpoint = 34.120.50.1:51820
AllowedIPs = 10.0.0.0/16
PersistentKeepalive = 15

所有 Fly 应用之间的通信都通过加密隧道进行,确保数据安全。

全球数据中心分布

区域位置覆盖范围
北美纽约、旧金山、洛杉矶、达拉斯、西雅图北美用户
欧洲阿姆斯特丹、法兰克福、伦敦、巴黎欧洲用户
亚太香港、新加坡、东京、悉尼、首尔亚太用户
南美圣保罗南美用户

IMPORTANT

Fly.io 持续扩展数据中心,具体可用区域请参考 flyctl platform regions 输出。


核心概念解析

1. Fly Application

Fly 应用是部署和管理的核心单位:

# fly.toml - 应用配置
app = "my-app-name"
 
# 基础配置
kill_signal = "SIGINT"
kill_timeout = "5s"
 
# 扩展性配置
[deploy]
  strategy = "rolling"
 
# 健康检查
[[services]]
  internal_port = 3000
  
  [[services.ports]]
    port = 80
    handlers = ["http"]
  
  [[services.ports]]
    port = 443
    handlers = ["tls", "http"]
  
  [[services.checks]]
    path = "/health"
    interval = "10s"
    timeout = "2s"

2. Fly Proxy

Fly Proxy 是边缘流量管理器,负责:

功能说明
负载均衡自动分发流量到多个实例
SSL 终止自动 HTTPS 证书管理
健康检查自动移除不健康实例
流量加密内部通信加密传输
速率限制防止 DDoS 和滥用

3. Fly Machine

Fly Machine 是 Fly.io 的核心计算单元:

{
  "id": "mach-abc123",
  "name": "web-0",
  "config": {
    "image": "registry.fly.io/myapp:latest",
    "env": {
      "NODE_ENV": "production"
    },
    "services": {
      "ports": [{"port": 3000}],
      "checks": [{
        "type": "http",
        "path": "/health",
        "interval": "10s"
      }]
    }
  },
  "region": "hkg",
  "state": "started"
}

4. 热迁移

Fly.io 支持机器的热迁移,可在不停机的情况下转移实例:

迁移前:香港 Machine(负载高)
        ↓ 执行热迁移
迁移后:新加坡 Machine(负载均衡)

热迁移优势:

  • 零停机时间
  • 保持会话连接
  • 自动更新就近部署

Fly Volumes 持久存储

概述

Fly Volumes 是 Fly.io 提供的本地持久化存储解决方案,基于 NVMe SSD,为每个应用提供独立的存储卷。

NOTE

Fly Volumes 与传统云存储(如 AWS EBS)的核心区别在于:数据存储在本地,提供极低的读写延迟,但只能在同一区域内访问。

核心特性

特性说明
持久性数据在重启后保留
本地性能NVMe SSD,延迟 < 1ms
独立卷每个应用独享存储
区域限制只能在创建区域内挂载
容量选择1GB 到 256GB 可选

创建和使用 Volume

# 创建 Volume
fly volumes create my_data --region hkg --size 10
 
# 查看 Volume
fly volumes list
 
# 输出示例
ID                   Name    Region  SizeGB  UsedGB  Encryption
vol_abc123           my_data  hkg     10      2.3     aes-256

Volume 配置

# fly.toml 中配置 Volume
[mounts]
  source = "my_data"
  destination = "/data"

应用示例:数据库存储

# PostgreSQL 使用 Fly Volume
import os
 
DATABASE_URL = os.getenv("DATABASE_URL", 
    "postgresql://user:pass@localhost:5432/mydb")
 
# Fly.io 自动注入的 Volume 路径
DATA_DIR = "/data/postgres"
 
# 应用配置
FLASK_ENV = "production"
SQLALCHEMY_DATABASE_URI = DATABASE_URL
SQLALCHEMY_TRACK_MODIFICATIONS = False

Volume 限制与注意事项

限制说明
区域绑定Volume 不能跨区域移动
单写原则同时只有一个 Machine 可写
容量固定创建后不能动态扩容(需创建新 Volume)
备份依赖需自行实现数据备份

IMPORTANT

Fly Volumes 不支持多实例共享写入。如果需要多实例共享存储,考虑使用 Tigris(Fly.io 对象存储)或外部数据库服务。

备份策略

# 方案 1:备份到 Tigris(Fly.io 对象存储)
flyctl storage create
 
# 方案 2:定时备份脚本
#!/bin/bash
# backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
pg_dump -Fc mydb > /tmp/backup_$DATE.dump
curl -X PUT -T /tmp/backup_$DATE.dump \
  https://storage.googleapis.com/my-bucket/

Fly Machines 微虚拟机

什么是 Fly Machines

Fly Machines 是基于 Firecracker 微虚拟机的计算单元,每个 Machine 是一个轻量级独立虚拟机,提供比容器更强的隔离性,同时保持毫秒级启动速度。

Firecracker 技术

Firecracker 是 AWS 开源的微虚拟机技术,特性:

特性说明
启动时间< 125ms(冷启动)
内存开销~5MB 基础内存
安全隔离硬件虚拟化(KVM)
资源效率可在裸机上运行数百个实例

Machine 配置

# machine.yaml
version: "2"
kind: machine
 
services:
  - protocol: tcp
    internal_port: 8080
 
machine:
  image: "registry.fly.io/myapp:v1"
  
  # 计算资源
  resources:
    cpu: 2          # vCPU 数量
    memory: 512mb    # 内存大小
  
  # 自动扩缩容
  auto_destroy: false
  size: "performance"
  
  # 健康检查
  checks:
    - type: http
      path: /health
      interval: 10s
      timeout: 2s
 
  # 环境变量
  env:
    NODE_ENV: production
    PORT: "8080"

Machine 生命周期

创建 → 启动 → 运行 → 健康检查 → 自动恢复
                    ↓
              扩展/缩减
                    ↓
              停止/销毁

Fly Apps V2 架构

Fly.io 的新版架构允许更细粒度的 Machine 管理:

# 使用 Fly Python SDK 管理 Machines
from fly.api import Fly
 
client = Fly()
 
# 创建 Machine
machine = client.machines.create(
    name="api-server-1",
    config={
        "image": "registry.fly.io/myapp:latest",
        "cpus": 2,
        "memory_mb": 512,
        "region": "hkg",
        "env": {"PORT": "8080"}
    }
)
 
# 列出所有 Machines
machines = client.machines.list()
for m in machines:
    print(f"{m.name}: {m.state}")
 
# 停止 Machine
client.machines.stop(machine.id)
 
# 删除 Machine
client.machines.destroy(machine.id)

多区域部署策略

自动就近路由

Fly.io 的 Anycast 网络自动将用户路由到最近数据中心:

用户(上海)→ Fly Proxy → 香港数据中心(延迟 ~30ms)
用户(北京)→ Fly Proxy → 香港数据中心(延迟 ~50ms)
用户(纽约)→ Fly Proxy → 纽约数据中心(延迟 ~10ms)

手动区域配置

# 指定部署区域
[deploy]
  release_command = "npm run migrate"
  strategy = "rolling"
 
# 区域配置
[env]
  PRIMARY_REGION = "hkg"
 
[regions]
  default = "hkg"
  zones = ["hkg", "sin", "nrt", "syd"]

跨区域数据库同步

# 多区域数据库配置
import os
 
class DatabaseConfig:
    # Fly.io 自动注入的区域信息
    FLY_REGION = os.getenv("FLY_REGION", "unknown")
    
    # 根据区域选择数据库
    DB_URLS = {
        "hkg": "postgresql://hkg.db.internal:5432/mydb",
        "sin": "postgresql://sin.db.internal:5432/mydb",
        "nrt": "postgresql://nrt.db.internal:5432/mydb",
    }
    
    @classmethod
    def get_url(cls):
        return cls.DB_URLS.get(cls.FLY_REGION, cls.DB_URLS["hkg"])
    
    @classmethod
    def is_primary(cls):
        return cls.FLY_REGION == os.getenv("PRIMARY_REGION", "hkg")

全球复制策略

┌─────────────────────────────────────────────────┐
│              Fly.io 全球复制                     │
├─────────────────────────────────────────────────┤
│                                                 │
│  Primary (香港) ←→ Replica (新加坡)              │
│       ↓                    ↓                   │
│  写入/更新          只读查询                    │
│       ↓                    ↓                   │
│  实时同步            延迟复制                  │
│                                                 │
└─────────────────────────────────────────────────┘

价格模型详解

按量付费 vs 月付计划

计费方式说明适用场景
按量付费按实际使用计费开发测试、低流量应用
月付计划固定月费 + 配额生产应用、可预估流量

按量付费明细

资源单价说明
vCPU$3.194/vCPU/天基础 VM 小型
内存$0.348/GB/天
卷存储$0.15/GB/月
出站流量$0.12/GB前 10TB
入站流量免费
Anycast IP$2/月

月付计划

计划价格包含资源
Hobby免费1x 共享 CPU, 256MB RAM, 1GB 存储
Standard$5/月1x vCPU, 512MB RAM, 3GB 存储
Pro$20/月2x vCPU, 1GB RAM, 10GB 存储
Pro Plus$50/月4x vCPU, 2GB RAM, 50GB 存储

成本计算示例

应用配置:
- 2 个 vCPU
- 1GB 内存
- 20GB 存储
- 100GB 月流量

计算:
CPU: 2 × $3.194/天 × 30天 = $191.64
内存: 1GB × $0.348/天 × 30天 = $10.44
存储: 20GB × $0.15/月 = $3.00
流量: 100GB × $0.12 = $12.00
─────────────────────────────────
总计: $217.08/月

TIP

对于低流量应用,使用月付计划更经济。例如 Standard 计划 $5/月相当于 2.5 个 vCPU 小时,远低于按量付费。

免费配额

资源免费额度
共享 CPU3 台机器/月
带宽160GB 出站/月
Volume3GB/月
构建时间无限制

与 Cloudflare Workers 对比

核心定位差异

维度Fly.ioCloudflare Workers
计算模型持久进程(VM)Serverless 函数
冷启动~200ms< 5ms
执行时长无限制50ms - 30s(付费可达 60min)
WebSocket✅ 原生支持⚠️ Durable Objects
持久存储✅ Volumes⚠️ D1/KV/R2
地理位置边缘数据中心300+ PoPs
定价模型按资源计费按请求计费

功能对比表

功能Fly.ioCloudflare Workers
Node.js✅ 完整支持✅ 完整支持
Python
Go✅(WASM)
Rust✅(WASM)
Docker❌(Workers only)
WebSocket⚠️ DO required
gRPC
长连接
持久计算❌(Durable Objects)
边缘数据库✅ D1
边缘 KV✅ Workers KV
对象存储✅ Tigris✅ R2

性能对比

测试场景Fly.ioCloudflare Workers
API 响应时间(亚太)~80ms~20ms
冷启动时间200-500ms< 5ms
吞吐量极高
持久连接优秀一般
复杂计算优秀受限

选型建议

场景推荐理由
API 后端Fly.io持久进程、无时长限制
静态 + 简单逻辑Workers超低延迟、全球覆盖
WebSocket 应用Fly.io原生支持
实时游戏Fly.io无冷启动延迟
CDN 边缘计算Workers全球 300+ PoPs
数据库密集型Fly.ioVolumes 性能好
简单 SSR两者皆可根据生态选择

实战部署指南

1. 初始化项目

# 安装 flyctl
curl -L https://fly.io/install.sh | sh
 
# 登录
flyctl auth login
 
# 初始化应用
cd my-project
flyctl launch

2. 配置应用

# fly.toml
app = "my-app-name"
primary_region = "hkg"
 
[build]
  builder = "heroku/buildpacks:20"
 
[env]
  PORT = "8080"
  NODE_ENV = "production"
 
[[services]]
  internal_port = 8080
  
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
  
  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443
    
  [[services.ports]]
    handlers = ["http"]
    port = 80
  
  [[services.checks]]
    path = "/health"
    interval = "10s"
    timeout = "2s"

3. 部署命令

# 部署
flyctl deploy
 
# 查看状态
flyctl status
 
# 查看日志
flyctl logs
 
# SSH 进入机器
flyctl ssh console

4. 自定义 Dockerfile 部署

# Dockerfile
FROM node:20-alpine
 
WORKDIR /app
 
COPY package*.json ./
RUN npm ci --only=production
 
COPY . .
 
EXPOSE 3000
 
CMD ["node", "server.js"]
# fly.toml 中指定 Dockerfile
[build]
  dockerfile = "Dockerfile"

5. 数据库部署

# 部署 PostgreSQL
flyctl postgres create --name my-db --region hkg
 
# 附加到应用
flyctl postgres attach --app my-app my-db
 
# 获取连接信息
flyctl postgres connect -a my-db

6. 自动扩缩容

# 自动扩缩容配置
[autoscale]
  min_machines = 1
  max_machines = 10
  
  [autoscale.memory]
    min_mb = 256
    max_mb = 1024
    
  [autoscale.cpu]
    threshold = 70  # CPU 使用率阈值

选型建议

选择 Fly.io 的充分条件

  • ✅ 需要持久进程或长连接
  • ✅ 需要 WebSocket/gRPC 支持
  • ✅ 应用需要 > 30s 执行时间
  • ✅ 需要本地持久存储
  • ✅ 需要完整的 Linux 环境
  • ✅ 需要多区域部署
  • ✅ 预算可控(按资源计费)

不选择 Fly.io 的场景

  • ❌ 超简单边缘函数(选择 Cloudflare Workers)
  • ❌ 严格预算控制(选择 Vercel/Netlify)
  • ❌ 主要使用 AWS 生态(选择 AWS Lambda)
  • ❌ 需要免费托管静态站点(选择 Vercel)

混合使用策略

Edge 层:Cloudflare Workers(静态资源、简单路由)
        ↓
Backend 层:Fly.io(API、WebSocket、持久计算)
        ↓
Database 层:PlanetScale/Turso(分布式数据库)

参考资料


服务概述与定位

Fly.io 在现代边缘计算中的角色

Fly.io 是边缘计算领域的创新者,它将「让应用靠近用户」这一理念做到了极致。与传统云服务将数据中心作为中心不同,Fly.io 通过 Anycast 路由和 Firecracker 微虚拟机技术,将应用部署到全球多个边缘节点。

平台核心价值

┌─────────────────────────────────────────────────────────────────────┐
│                    Fly.io 核心价值体系                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐ │
│  │                    就近计算                                   │ │
│  │                                                               │ │
│  │  用户(上海) ────────→ Fly Edge(香港) ───→ 延迟 ~30ms    │ │
│  │  用户(北京) ────────→ Fly Edge(香港) ───→ 延迟 ~50ms    │ │
│  │  用户(纽约) ────────→ Fly Edge(纽约)  ───→ 延迟 ~10ms    │ │
│  │                                                               │ │
│  └───────────────────────────────────────────────────────────────┘ │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐ │
│  │                    容器级隔离                                 │ │
│  │                                                               │ │
│  │  Firecracker VM → 毫秒启动 → 硬件虚拟化隔离                   │ │
│  │  与容器相比:更强隔离性 + 更低开销                            │ │
│  │                                                               │ │
│  └───────────────────────────────────────────────────────────────┘ │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐ │
│  │                    持久存储                                   │ │
│  │                                                               │ │
│  │  Fly Volumes → NVMe SSD → 区域绑定 → 高性能本地存储           │ │
│  │                                                               │ │
│  └───────────────────────────────────────────────────────────────┘ │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

技术栈全景

# Fly.io 技术栈
flyio_stack = {
    # 计算层
    "compute": {
        "machines": "Firecracker VMs",
        "isolation": "硬件虚拟化 (KVM)",
        "startup_time": "< 125ms",
        "memory_overhead": "~5MB",
    },
    
    # 网络层
    "network": {
        "routing": "Anycast",
        "tunnel": "WireGuard",
        "tls": "自动 Let's Encrypt",
        "load_balancing": "Fly Proxy",
    },
    
    # 存储层
    "storage": {
        "volumes": "NVMe SSD",
        "object_storage": "Tigris",
        "regions": "区域绑定",
    },
    
    # 支持的应用
    "supported_apps": [
        "Docker 容器",
        "Node.js",
        "Python (FastAPI/Flask/Django)",
        "Go",
        "Ruby",
        "PHP",
        "Rust",
        "Elixir",
        "Static Sites",
        "gRPC",
        "WebSocket",
    ],
}

完整配置教程

安装 Flyctl CLI

# macOS
brew install flyctl
 
# Linux
curl -L https://fly.io/install.sh | sh
 
# Windows (PowerShell)
iwr https://fly.io/install.ps1 -useb | iex
 
# npm
npm install -g @flydotio/dockerfile
 
# 验证安装
flyctl version

认证和初始化

# 登录
flyctl auth login
 
# 使用 GitHub 登录
flyctl auth login --browser github
 
# 查看当前登录状态
flyctl auth whoami
 
# 登出
flyctl auth logout
 
# 组织登录
flyctl auth login --org my-org

创建应用

# 方法 1: 交互式创建
flyctl apps create
# 输入应用名称
# 选择组织
 
# 方法 2: 从 Dockerfile
flyctl launch --image nginx:latest
 
# 方法 3: 从现有配置
flyctl launch --no-generate
 
# 方法 4: 从 GitHub
flyctl launch --from https://github.com/username/repo
 
# 查看应用列表
flyctl apps list
 
# 查看应用详情
flyctl apps info myapp

fly.toml 完整配置

# fly.toml - Fly.io 应用配置
 
# ─────────────────────────────────────────────────────────
# 应用基础配置
# ─────────────────────────────────────────────────────────
app = "my-app-name"
primary_region = "hkg"  # 主要区域
 
# Kill 信号和超时
kill_signal = "SIGINT"
kill_timeout = "5s"
 
# ─────────────────────────────────────────────────────────
# 构建配置
# ─────────────────────────────────────────────────────────
[build]
    # 使用预构建镜像
    image = "nginx:alpine"
    
    # 或使用 Dockerfile
    # dockerfile = "Dockerfile"
    
    # 或使用 Buildpacks
    # builder = "heroku/buildpacks:20"
 
# ─────────────────────────────────────────────────────────
# 环境变量
# ─────────────────────────────────────────────────────────
[env]
    PORT = "8080"
    NODE_ENV = "production"
    LOG_LEVEL = "info"
 
# ─────────────────────────────────────────────────────────
# 挂载卷
# ─────────────────────────────────────────────────────────
[mounts]
    source = "my_data"
    destination = "/data"
 
# ─────────────────────────────────────────────────────────
# 服务配置(HTTP/HTTPS)
# ─────────────────────────────────────────────────────────
[[services]]
    # 内部端口
    internal_port = 8080
    
    # 并发限制
    [services.concurrency]
        hard_limit = 25
        soft_limit = 20
    
    # HTTP 端口
    [[services.ports]]
        port = "80"
        handlers = ["http"]
        force_https = true
    
    # HTTPS 端口
    [[services.ports]]
        port = "443"
        handlers = ["tls", "http"]
    
    # 健康检查
    [[services.checks]]
        name = "health"
        path = "/health"
        interval = "10s"
        timeout = "2s"
        retries = 3
        grace_period = "10s"
        method = "get"
        protocol = "http"
    
    # TCP 检查
    [[services.checks]]
        name = "tcp-check"
        port = 5432
        interval = "10s"
        timeout = "5s"
 
# ─────────────────────────────────────────────────────────
# 区域配置
# ─────────────────────────────────────────────────────────
# 主要区域
[regions]
    default = "hkg"
    
# 允许的区域
[regions.distant]
    regions = ["sin", "nrt", "syd"]
 
# 区域HA(高可用)
[ha]
    regions = ["hkg", "sin"]
 
# ─────────────────────────────────────────────────────────
# 部署策略
# ─────────────────────────────────────────────────────────
[deploy]
    strategy = "rolling"  # rolling, canary, immediate, blue
    release_command = "npm run migrate"
    max_unavailable = 0.25
    max_surge = 1
 
# ─────────────────────────────────────────────────────────
# 自动扩缩容
# ─────────────────────────────────────────────────────────
[autoscale]
    min_machines = 1
    max_machines = 10
    
    [autoscale.memory]
        min_mb = 256
        max_mb = 1024
        target_mem_percent = 70
    
    [autoscale.cpu]
        threshold = 75
 
# ─────────────────────────────────────────────────────────
# HTTP/2 和 WebSocket
# ─────────────────────────────────────────────────────────
[http_service]
    internal_port = 8080
    force_https = true
    auto_stop_machines = true
    auto_start_machines = true
    min_machines_running = 0
    processes = ["app"]
 
# ─────────────────────────────────────────────────────────
# SSH 配置
# ─────────────────────────────────────────────────────────
[vm]
    size = "shared-cpu-1x"
    memory = "512mb"
    cpu_kind = "shared"
    cpus = 1
 
# ─────────────────────────────────────────────────────────
# 监控
# ─────────────────────────────────────────────────────────
[metrics]
    port = 9090
    path = "/metrics"
 
# ─────────────────────────────────────────────────────────
# Secrets
# ─────────────────────────────────────────────────────────
# 使用 flyctl secrets set 设置敏感数据
# flyctl secrets set DATABASE_URL=xxx
# flyctl secrets set API_KEY=xxx

核心功能详解

Fly Machines 深度解析

Machine 配置选项

# machine.yaml - Machine 详细配置
version: "2"
kind: machine
 
# 服务配置
services:
  - protocol: tcp
    internal_port: 8080
    concurrency:
      type: "connection"
      hard_limit: 25
      soft_limit: 20
 
# Machine 配置
machine:
  # 镜像
  image: "registry.fly.io/myapp:v1"
  
  # 自动销毁
  auto_destroy: true
  
  # 机器大小
  size: "performance-2x"
  
  # 区域
  region: "hkg"
  
  # 计算资源
  resources:
    cpu: 2
    memory: 1024mb
  
  # 自动停止(节省成本)
  auto_stop: true
  auto_start: true
  
  # 休眠时间(分钟)
  guest_preparation_time: 3
  
  # 健康检查
  checks:
    - type: "http"
      name: "http-check"
      interval: "10s"
      timeout: "2s"
      retries: 3
      path: "/health"
      method: "GET"
  
  # 环境变量
  env:
    NODE_ENV: "production"
    PORT: "8080"
  
  # 挂载
  mounts:
    - volume: "my_data"
      path: "/data"
  
  # 启动命令
  cmd: ["node", "server.js"]
  
  # 入口点
  entrypoint: ["/bin/sh", "-c"]

Machine 生命周期管理

# 使用 Fly API 管理 Machines
import requests
 
class FlyMachines:
    def __init__(self, api_token):
        self.api_token = api_token
        self.base_url = "https://api.machines.dev"
        self.headers = {
            "Authorization": f"Bearer {api_token}",
            "Content-Type": "application/json",
        }
    
    def create_machine(self, app_name, config):
        """创建新 Machine"""
        url = f"{self.base_url}/v1/apps/{app_name}/machines"
        response = requests.post(url, headers=self.headers, json=config)
        return response.json()
    
    def list_machines(self, app_name):
        """列出所有 Machines"""
        url = f"{self.base_url}/v1/apps/{app_name}/machines"
        response = requests.get(url, headers=self.headers)
        return response.json()
    
    def get_machine(self, machine_id):
        """获取 Machine 详情"""
        url = f"{self.base_url}/v1/machines/{machine_id}"
        response = requests.get(url, headers=self.headers)
        return response.json()
    
    def start_machine(self, machine_id):
        """启动 Machine"""
        url = f"{self.base_url}/v1/machines/{machine_id}/start"
        response = requests.post(url, headers=self.headers)
        return response.json()
    
    def stop_machine(self, machine_id):
        """停止 Machine"""
        url = f"{self.base_url}/v1/machines/{machine_id}/stop"
        response = requests.post(url, headers=self.headers)
        return response.json()
    
    def delete_machine(self, machine_id):
        """删除 Machine"""
        url = f"{self.base_url}/v1/machines/{machine_id}"
        response = requests.delete(url, headers=self.headers)
        return response.json()
    
    def wait_for_state(self, machine_id, target_state, timeout=60):
        """等待 Machine 进入目标状态"""
        import time
        start = time.time()
        while time.time() - start < timeout:
            machine = self.get_machine(machine_id)
            if machine.get("state") == target_state:
                return True
            time.sleep(1)
        return False

Fly Volumes 深度解析

卷的高级配置

# 创建带加密的卷
fly volumes create my_data \
    --region hkg \
    --size 10 \
    --encrypted
 
# 查看卷详情
fly volumes show vol_abc123
 
# 列出卷
fly volumes list
 
# 删除卷
fly volumes destroy vol_abc123
 
# 调整卷大小(创建新卷)
fly volumes create my_data_new --region hkg --size 20
# 然后迁移数据

数据库存储配置

# PostgreSQL 使用 Fly Volumes
import os
 
# 获取卷路径
DATA_DIR = os.getenv("FLY_VOLUMES_DIR", "/data")
POSTGRES_DATA_DIR = f"{DATA_DIR}/postgres"
 
# 环境变量
DATABASE_URL = os.getenv("DATABASE_URL", 
    f"postgresql://user:pass@localhost:5432/mydb")
    
# 启动脚本
STARTUP_SCRIPT = """
#!/bin/bash
mkdir -p {data_dir}
chown postgres:postgres {data_dir}
exec postgres \
    -D {data_dir} \
    -c config_file=/etc/postgresql/postgresql.conf
""".format(data_dir=POSTGRES_DATA_DIR)

网络深度配置

自定义域名

# 添加域名
fly certs add example.com
fly certs add www.example.com
 
# 检查证书状态
fly certs show example.com
 
# 删除证书
fly certs remove example.com
 
# 查看 DNS 配置说明
fly certs add example.com --show-dns

内网服务

# fly.toml - 内网服务配置
# 内网服务不需要公开端口
 
[[services]]
    internal_port = 8080
    
    # 只允许内网访问
    [[services.ports]]
        handlers = ["tls"]
        port = 443
    
    # 内网连接
    [[services.tcp]]
        host = "my-internal-service.fly.dev"
        port = 8080
 
# 服务间连接
# 使用 .internal 域名
# myapp.internal.fly.dev
# 或机器 IP

部署配置

多种部署方式

1. Dockerfile 部署

# Dockerfile
FROM node:20-alpine
 
WORKDIR /app
 
COPY package*.json ./
RUN npm ci --only=production
 
COPY . .
 
EXPOSE 8080
 
# Fly.io 会自动设置 PORT
CMD ["node", "server.js"]
# fly.toml
[build]
    dockerfile = "Dockerfile"
 
[[services]]
    internal_port = 8080
    [[services.ports]]
        handlers = ["http", "tls"]
        port = 443

2. 多阶段构建

# Dockerfile
# ─────────────────────────────────────────────────────────
# Build stage
# ─────────────────────────────────────────────────────────
FROM node:20-alpine AS builder
 
WORKDIR /app
 
COPY package*.json ./
RUN npm ci
 
COPY . .
RUN npm run build
 
# ─────────────────────────────────────────────────────────
# Production stage
# ─────────────────────────────────────────────────────────
FROM node:20-alpine AS production
 
WORKDIR /app
 
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001
 
COPY package*.json ./
RUN npm ci --only=production
 
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
 
USER nodejs
 
EXPOSE 8080
 
CMD ["node", "dist/server.js"]

3. 预构建镜像部署

# 直接使用预构建镜像
fly launch --image nginx:alpine
 
# 自定义镜像
fly launch --imageregistry.fly.io/myapp:v1
 
# Docker Hub 镜像
fly launch --image redis:7-alpine

多区域部署

# fly.toml - 多区域配置
primary_region = "hkg"
 
# 默认区域
[regions]
    default = "hkg"
 
# 全球分布
[regions.distant]
    regions = ["sin", "nrt", "syd", "lax", "ewr", "ams"]
 
# 高可用配置
[ha]
    regions = ["hkg", "sin"]
# 应用级区域路由
from flask import Flask, request
 
app = Flask(__name__)
 
# Fly.io 自动设置 FLY_REGION
REGION = os.getenv("FLY_REGION", "unknown")
 
@app.route('/api/data')
def get_data():
    # 根据区域选择数据源
    if REGION == "hkg":
        data = get_from_hk_database()
    elif REGION == "sin":
        data = get_from_sg_database()
    else:
        data = get_from_default_database()
    
    return {
        "region": REGION,
        "data": data
    }

环境变量与密钥管理

Secrets 管理

# 设置 secrets
fly secrets set DATABASE_URL=postgresql://xxx
fly secrets set API_KEY=xxx
fly secrets set JWT_SECRET=xxx
 
# 批量设置
fly secrets set \
    DATABASE_URL=xxx \
    API_KEY=xxx \
    STRIPE_KEY=xxx
 
# 从文件设置
fly secrets set --file .env.production
 
# 查看 secrets
fly secrets list
 
# 删除 secret
fly secrets unset API_KEY
 
# Secrets 命名规范
# 使用大写下划线命名
# DATABASE_URL
# API_SECRET_KEY
# JWT_PRIVATE_KEY

多环境配置

# 创建 secrets 文件
# .secrets
DATABASE_URL=postgresql://user:pass@prod.db:5432/mydb
API_KEY=prod_api_key
JWT_SECRET=prod_jwt_secret
 
# 设置到生产环境
fly secrets set --app myapp-prod --file .secrets
 
# 查看环境
fly config env --app myapp-prod

CI/CD 集成

GitHub Actions

# .github/workflows/fly-deploy.yml
name: Fly.io Deployment
 
on:
  push:
    branches: [main]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Setup Flyctl
        uses: superfly/flyctl-actions/setup-flyctl@master
        with:
          flyctl-auth-token: ${{ secrets.FLY_API_TOKEN }}
 
      - name: Deploy to Fly.io
        run: |
          flyctl deploy \
            --app ${{ secrets.FLY_APP_NAME }} \
            --region hkg \
            --strategy rolling
 
      - name: Health Check
        run: |
          sleep 10
          curl -f https://${{ secrets.FLY_APP_NAME }}.fly.dev/health || exit 1
 
      - name: Show logs
        if: failure()
        run: flyctl logs --app ${{ secrets.FLY_APP_NAME }}

GitLab CI

# .gitlab-ci.yml
stages:
  - deploy
 
deploy:
  stage: deploy
  image: ubuntu:22.04
  before_script:
    - apt-get update && apt-get install -y curl
    - curl -L https://fly.io/install.sh | sh
    - export FLYCTL_INSTALL="/root/.fly"
    - export PATH="$FLYCTL_INSTALL/bin:$PATH"
  script:
    - flyctl auth login --token $FLY_API_TOKEN
    - flyctl deploy --app $FLY_APP_NAME --region hkg
  only:
    - main
  environment:
    name: production
    url: https://$FLY_APP_NAME.fly.dev

性能优化与缓存策略

机器大小选择

# fly.toml - 机器配置
[vm]
    size = "performance-2x"  # 2 vCPU, 4GB RAM
    cpus = 2
    memory = "4096mb"
规格vCPU内存适用场景
shared-cpu-1x1256MB开发/测试
shared-cpu-2x2512MB小型应用
performance-1x12GB中型应用
performance-2x24GB大型应用
performance-4x48GB高性能需求
performance-8x816GB旗舰配置

自动扩缩容

# fly.toml - 自动扩缩容配置
[autoscale]
    min_machines = 1
    max_machines = 10
    
    [autoscale.memory]
        min_mb = 256
        max_mb = 2048
        target_mem_percent = 70
    
    [autoscale.cpu]
        threshold = 80

缓存策略

# Fly Volumes 上的 Redis 配置
# redis.conf
bind 0.0.0.0
port 6379
maxmemory 256mb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
 
# Fly Volumes 路径
dir /data
dbfilename dump.rdb

成本估算与选型建议

成本计算器

# Fly.io 成本计算
class FlyCostCalculator:
    # 基础价格(按量付费)
    pricing = {
        "cpu_per_vcpu_day": 3.194,
        "memory_per_gb_day": 0.348,
        "volume_per_gb_month": 0.15,
        "outbound_bandwidth_per_gb": 0.12,
        "anycast_ip_month": 2.00,
    }
    
    # 月付计划
    plans = {
        "hobby": {
            "price": 0,
            "cpu": "shared-cpu",
            "memory": 256,
            "storage": 3,
            "bandwidth": 160,  # GB
        },
        "standard": {
            "price": 5,
            "cpu": "shared-cpu",
            "memory": 512,
            "storage": 10,
            "bandwidth": "unlimited",
        },
        "pro": {
            "price": 20,
            "cpu": "performance",
            "memory": 2048,
            "storage": 50,
            "bandwidth": "unlimited",
        },
    }
    
    def calculate_usage_cost(
        self,
        cpu_vcpus: float,
        memory_gb: float,
        storage_gb: float,
        bandwidth_gb: float,
        days: int = 30
    ) -> dict:
        """计算按量付费成本"""
        costs = {
            "cpu": cpu_vcpus * self.pricing["cpu_per_vcpu_day"] * days,
            "memory": memory_gb * self.pricing["memory_per_gb_day"] * days,
            "storage": storage_gb * self.pricing["volume_per_gb_month"],
            "bandwidth": max(0, bandwidth_gb - 160) * self.pricing["outbound_bandwidth_per_gb"],
        }
        costs["total"] = sum(costs.values())
        return costs
    
    def compare_plans(
        self,
        cpu_vcpus: float,
        memory_gb: float,
        storage_gb: float
    ) -> dict:
        """比较月付计划和按量付费"""
        results = {}
        
        # 计算按量付费
        usage_cost = self.calculate_usage_cost(cpu_vcpus, memory_gb, storage_gb, 0)
        results["usage"] = usage_cost["total"]
        
        # 检查各计划
        for name, plan in self.plans.items():
            if memory_gb <= plan["memory"]:
                results[name] = plan["price"]
        
        return results

选型建议矩阵

场景推荐配置理由
开发/测试Hobby 免费版免费额度足够
小型应用Standard $5/月固定价格,易于预算
中型应用按量付费灵活,成本可控
高流量应用Pro $20/月性能保证
数据库密集型性能机器 + Volumes高 IOPS

常见问题与解决方案

部署问题

问题:部署失败

# 检查日志
fly logs
 
# 常见原因:
 
# 1. 端口配置错误
# 确保应用监听 PORT 环境变量
# fly.toml 中 internal_port 正确
 
# 2. 健康检查失败
# 确保 /health 端点返回 200
curl http://localhost:8080/health
 
# 3. 资源不足
# flyctl scale show
# flyctl scale memory 1024

问题:构建超时

# 原因:构建时间过长
# 解决方案:
 
# 1. 优化 Dockerfile
# 使用更小的基础镜像
FROM alpine:3.19
 
# 2. 增加构建超时
flyctl deploy --no-cache
 
# 3. 使用预构建镜像
fly launch --image node:20-alpine

运行时问题

问题:应用响应慢

# 检查资源使用
flyctl status
flyctl metrics
 
# 增加资源
flyctl scale memory 2048
flyctl scale cpu 2
 
# 检查区域延迟
flyctl doctor

问题:频繁重启

# 检查重启原因
flyctl events --type crash
 
# 常见原因:
 
# 1. OOM
# 增加内存
flyctl scale memory 1024
 
# 2. 健康检查失败
# 检查应用健康端点
# 调整健康检查配置

网络问题

问题:无法访问应用

# 检查服务状态
flyctl services list
 
# 检查证书
flyctl certs list
 
# 重启应用
flyctl restart
 
# 检查防火墙
flyctl wireguard list

存储问题

问题:卷空间不足

# 查看卷使用
fly volumes list
 
# 创建新卷
fly volumes create new_data --region hkg --size 50
 
# 扩展现有卷(创建新卷然后迁移)
# 1. 创建新卷
fly volumes create expanded_data --region hkg --size 100
 
# 2. 在应用中添加新挂载
# fly.toml
[mounts]
    source = "expanded_data"
    destination = "/data"
 
# 3. 迁移数据
flyctl ssh console
# 在机器内执行: cp -r /old/data/* /new/data/

数据库问题

问题:PostgreSQL 连接失败

# 检查数据库状态
flyctl postgres status
 
# 获取连接信息
flyctl postgres connect -a mydb
 
# 启动数据库
flyctl postgres start -a mydb
 
# 停止数据库
flyctl postgres stop -a mydb
 
# 重启数据库
flyctl postgres restart -a mydb
 
# 备份数据库
flyctl postgres import -a mydb < backup.dump

问题:Redis 连接失败

# 检查 Redis 状态
flyctl redis status
 
# 获取连接信息
flyctl redis connect -a myredis
 
# 查看 Redis 日志
flyctl logs --app myredis

高级功能

团队协作

团队管理

# 创建组织
flyctl orgs create my-org
 
# 列出组织
flyctl orgs list
 
# 切换组织
flyctl orgs switch my-org
 
# 添加成员
flyctl orgs add-member user@example.com my-org
 
# 移除成员
flyctl orgs remove-member user@example.com my-org
 
# 设置成员角色
flyctl orgs update-member user@example.com --role developer
# 角色: owner, member, viewer

访问控制

# fly.toml - 项目访问控制
# 在 flyctl apps create 时设置
flyctl apps create myapp --org my-org
 
# 转移应用
flyctl apps transfer myapp --org new-org
 
# 查看应用权限
flyctl access-tokens list

Fly Apps V2 架构

Machine API 深度使用

# 使用 Fly API 创建和管理 Machines
import requests
import json
 
class FlyMachinesAPI:
    def __init__(self, token, app_name):
        self.token = token
        self.app_name = app_name
        self.base_url = f"https://api.machines.dev/v1/apps/{app_name}"
        self.headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        }
    
    def create_machine(self, config):
        """创建 Machine"""
        url = f"{self.base_url}/machines"
        response = requests.post(url, headers=self.headers, json=config)
        return response.json()
    
    def list_machines(self):
        """列出所有 Machines"""
        url = f"{self.base_url}/machines"
        response = requests.get(url, headers=self.headers)
        return response.json()
    
    def get_machine(self, machine_id):
        """获取 Machine 详情"""
        url = f"{self.base_url}/machines/{machine_id}"
        response = requests.get(url, headers=self.headers)
        return response.json()
    
    def update_machine(self, machine_id, config):
        """更新 Machine"""
        url = f"{self.base_url}/machines/{machine_id}"
        response = requests.post(url, headers=self.headers, json=config)
        return response.json()
    
    def delete_machine(self, machine_id):
        """删除 Machine"""
        url = f"{self.base_url}/machines/{machine_id}"
        response = requests.delete(url, headers=self.headers)
        return response.status_code == 204
    
    def exec_in_machine(self, machine_id, cmd):
        """在 Machine 中执行命令"""
        url = f"{self.base_url}/machines/{machine_id}/exec"
        response = requests.post(
            url, 
            headers=self.headers,
            json={"cmd": cmd, "timeout": 30}
        )
        return response.json()
 
# 使用示例
api = FlyMachinesAPI(token="your-token", app_name="myapp")
 
# 创建 Machine
config = {
    "region": "hkg",
    "config": {
        "image": "nginx:alpine",
        "auto_destroy": True,
        "restart": {
            "policy": "on-failure",
            "max_retries": 3
        }
    }
}
machine = api.create_machine(config)
print(f"Created machine: {machine['id']}")
 
# 列出 Machines
machines = api.list_machines()
for m in machines:
    print(f"{m['id']}: {m['state']}")
 
# 执行命令
result = api.exec_in_machine(machine['id'], "nginx -v")
print(result)

监控与日志

日志管理

# 查看日志
flyctl logs
 
# 过滤日志
flyctl logs --filter error
flyctl logs --filter "POST /api"
 
# 查看特定机器日志
flyctl logs --machine mach_abc123
 
# 导出日志
flyctl logs > app.log
 
# 实时日志
flyctl logs -f
 
# 日志级别
# 默认: info
# 调试模式
flyctl logs --verbose

指标监控

# 查看基本指标
flyctl status
 
# 查看详细指标
flyctl metrics
 
# 导出指标
flyctl metrics --json > metrics.json
 
# 集成 Prometheus
# 添加 Prometheus 端点
# fly.toml
[metrics]
    port = 9090
    path = "/metrics"
 
# Prometheus 配置
# prometheus.yml
scrape_configs:
  - job_name: 'fly-apps'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['myapp.fly.dev']

备份与恢复

数据库备份

# PostgreSQL 备份
# 1. 连接到数据库
flyctl postgres connect -a mydb
 
# 2. 执行备份
pg_dump -Fc mydb > backup.dump
 
# 3. 上传到存储
flyctl storage create
# 使用 Tigris 存储
 
# 恢复备份
pg_restore -Fc -d mydb backup.dump
 
# 自动备份配置
# fly.toml
[backup]
    enabled = true
    schedule = "0 2 * * *"  # 每天凌晨2点
    retention = 7  # 保留7天

参考资料

官方资源

相关工具

工具说明
flyctl命令行工具
Fly DashboardWeb 控制台
Fly Machines API编程式管理
Tigris对象存储
LiteFS分布式 SQLite
Fly VolumesNVMe 存储
WireGuard安全隧道

学习资源

资源说明
Fly.io Academy官方教程
Fly.io Examples示例项目
Community Tutorials社区教程
YouTube Channel视频教程
GitHub Discussions讨论区

SUCCESS

Fly.io 是 vibecoding 工作流中部署后端服务的优秀选择。其边缘计算架构、持久存储能力和 WebSocket 支持,使其成为需要低延迟、高可用应用的最佳平台。对于需要快速原型验证但又希望拥有生产级基础设施的开发者,Fly.io 提供了完美的平衡。