- 云原生
- 后端
- DevOps
【免费下载链接】shuttle
Build & ship backends without writing any infrastructure files.
本文以 shuttle 开源仓库主 README 为核心展开,带你从零上手:安装
shuttleCLI、用模板初始化 Axum 项目、编写带数据库的 Rust 服务,并通过shuttle deploy在数十秒内完成生产部署。读完你将掌握 Shuttle 的完整工作流(安装 → 登录 → 初始化 → 本地运行 → 部署)、#[shuttle_runtime::main]宏与“资源即函数参数”的供给机制,以及 CLI 常用命令与项目配置文件Shuttle.toml的用法。
Shuttle 是什么
shuttle 是一个 Rust 原生的云端开发平台,其核心理念是:用几行代码获得资源并部署你的应用,无需编写任何基础设施文件(YAML、Dockerfile、Terraform 等)。仓库主页将其定位为 "Fastest Way to Build & Ship Rust Apps"(构建并交付 Rust 应用的最快方式),主打Simple. Easy. Joyful.的开发体验。
Shuttle 的核心特性(见 README.md):
- One-line Resource Provisioning(一行代码供给资源):在主文件中添加一行代码即可获得数据库等资源,不需要任何 config 或 yaml 文件;
- Rapid Development(快速开发):从项目初始化到部署上线只需约 2 分钟;供给资源到生产环境只需数秒;
- First-class support for popular Rust frameworks(一流的主流 Rust 框架支持):包括 Axum、Actix Web、Rocket,以及更多(见下文框架列表);
- Security(安全):平台负责安全与权限,开发者专注于编写好代码。
从仓库结构看,整个项目是一个 Cargo workspace(见 Cargo.toml),当前版本号为0.57.0,包含admin、api-client、builder、cargo-shuttle(CLI)、codegen(过程宏)、common、ifc、mcp、runtime、service等核心 crate,以及services/目录下为各 Web 框架提供的官方集成 crate。
快速开始:安装与登录
安装 Shuttle CLI
在 Linux 和 macOS 上,使用官方安装脚本(会自动根据你的 OS 与发行版选择正确的安装目标):
curl -sSfL https://www.shuttle.dev/install | bash在 Windows 上,使用 PowerShell 执行等价脚本:
iwr "https://www.shuttle.dev/install-win" | iex从仓库内的 install.sh 源码看,安装脚本会根据发行版走不同安装路径:Arch 系使用pacman、Alpine 使用apk,其余系统回退到二进制下载(cargo-shuttle-$VERSION-<target>.tar.gz)或cargo install --locked cargo-shuttle;脚本还会自动检测cargo/rustup是否安装,必要时引导通过 rustup 安装 Rust 工具链。安装产物是cargo-shuttle与shuttle两个命令(见 install.sh),因此你也可以直接通过 Cargo 手动安装:
cargo install --locked cargo-shuttle登录
安装完成后,登录你的 Shuttle 账号:
shuttle loginlogin命令默认走设备授权流程(device auth):CLI 通过 WebSocket 向 Shuttle Console 申请一次性令牌并自动打开浏览器,用户完成授权后 CLI 自动接收 API key(见 cargo-shuttle/src/lib.rs)。如果你更希望手动粘贴 API key,可以改用:
shuttle login --prompt # 或 shuttle login --api-key <YOUR_API_KEY>API key 会被持久化保存到全局配置文件(~/.config/shuttle/config.toml,Linux 下)中;也可以直接通过环境变量SHUTTLE_API_KEY提供(见 cargo-shuttle/src/config.rs)。
初始化项目:shuttle init
登录后,用内置模板初始化一个 Axum 项目:
shuttle init --template axum hello-world这会在hello-world/目录生成一个可运行的项目骨架。--template支持的模板在 cargo-shuttle/src/args.rs 的InitTemplateArg枚举中定义,包括:axum、actix-web、rocket、loco、salvo、poem、poise、rama、serenity、tower、warp,以及none(自定义服务,无框架模板)。每个模板对应官方示例仓库shuttle-examples中的固定子目录,例如axum对应axum/hello-world、actix-web对应actix-web/hello-world(见 cargo-shuttle/src/args.rs)。
init的更多选项(见 cargo-shuttle/src/args.rs):
| 参数 | 说明 |
|---|---|
--template <T>/-t <T> | 从官方示例克隆指定框架的 starter 模板 |
--from <git_url_or_local_path> | 从自定义 Git 仓库或本地路径克隆模板(与--template互斥) |
--subfolder <path> | 配合--from指定模板在源仓库中的子目录 |
--force-name | 跳过项目名合法性/可用性校验 |
--create-project/--create-env | 初始化时同时在上创建 Shuttle 项目 |
--no-git | 不初始化 Git 仓库(默认会执行git init并把.gitignore写入忽略规则) |
--path <dir> | 项目生成目录(默认当前目录) |
shuttle init底层的工作流程可以从 cargo-shuttle/src/init.rs 的generate_project中看到:
- 将模板克隆到临时目录(
gix浅克隆,等价于git clone --depth 1); - 把
Cargo.toml中的 crate 名改写为你的项目名;如果是 workspace 结构则改写在Shuttle.toml的name字段中; - 在
.gitignore(或--no-git时的.ignore)中补充/target、.shuttle*、Secrets*.toml等推荐忽略规则(见 cargo-shuttle/src/init.rs); - 将模板文件拷贝到目标目录(跳过
target与.git目录); - 若无现成 Git 仓库,则自动
git init。
交互模式下(不带任何参数直接运行shuttle init),CLI 会依次引导你登录、输入项目名、选择目录与模板(在线拉取官方模板清单,失败时回退到内置列表),并在最后询问是否同时在平台创建项目(见 cargo-shuttle/src/lib.rs)。
一键部署:shuttle deploy
进入项目目录,执行部署:
cd hello-world shuttle deploy部署成功后,你会看到类似下面的输出:
Service Name: hello-world Deployment ID: 3d08ac34-ad63-41c1-836b-99afdc90af9f Status: running Last Updated: 2022-04-01T08:32:34Z URI: https://hello-world.shuttleapp.rs此时应用已通过https://hello-world.shuttleapp.rs对外提供访问。shuttle deploy的常用参数(见 cargo-shuttle/src/args.rs):
--allow-dirty/--ad:允许在存在未提交改动时部署;--no-follow/--nf:只发起部署请求,不持续跟踪状态,立即退出;--raw:输出时不显示时间戳与日志来源标记;--secrets <file>:指定自定义 secrets 文件;--output-archive <path>:把构建归档写到本地文件而不真正发起部署(可用于离线检查)。
从源码看,deploy命令(cargo-shuttle/src/lib.rs)的完整链路为:读取 secrets → 通过cargo_metadata探测工作区中带有#[shuttle_runtime::main]的二进制 target 并收集构建参数(包名、二进制名、feature、shuttle-runtime 版本等,见 cargo-shuttle/src/builder.rs)→ 解析代码中的基础设施注解(parse_infra_from_code)→ 采集 Git 构建元信息(commit、branch、dirty 状态)→ 将项目文件打包为 zip 归档(make_archive)→ 上传归档 → 发起部署请求 → 跟踪部署状态直到Running或Failed,失败时自动拉取日志打印。部署状态机(pending → building → in progress → running/failed/stopped)定义在 common/src/models/deployment.rs。
本地先跑一跑:shuttle run
在上云之前,可以用shuttle run在本地验证应用。它会在默认端口 8000 启动服务(见 runtime/README.md):
shuttle run # 另开终端 curl http://localhost:8000/ # Hello, world!shuttle run的可选参数包括-p/--port <port>(服务端口,默认 8000)、--external(监听0.0.0.0以便局域网/外部设备访问)、--raw、--release(release 模式构建)、--bacon(基于 bacon 的 watch 模式热重载)等(见 cargo-shuttle/src/args.rs)。本地运行时,CLI 会在本机拉起一个临时的 provisioner 服务器模拟资源供给,并通过SHUTTLE_*环境变量把项目名、端口、API 地址等传给运行时(见 cargo-shuttle/src/lib.rs)。
Quick Look:一个完整的 Axum 应用演进示例
原始版本:普通 Axum Hello World
一个标准的 Axum 应用长这样(README.md):
use axum::{routing::get, Router}; #[tokio::main] async fn main() { let app = Router::new().route("/", get(hello_world)); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); println!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); } async fn hello_world() -> &'static str { "Hello, world!" }改造为 Shuttle 版本:去掉样板代码
要让应用能够用单条命令部署,只需把main函数标记为#[shuttle_runtime::main]并返回shuttle_axum::ShuttleAxum类型(README.md):
use axum::{routing::get, Router}; async fn hello_world() -> &'static str { "Hello, world!" } #[shuttle_runtime::main] async fn main() -> shuttle_axum::ShuttleAxum { let router = Router::new().route("/", get(hello_world)); Ok(router.into()) }对比可见,绑定地址、创建 listener、axum::serve等与基础设施相关的样板代码全部消失了——服务进程的监听地址由 Shuttle 运行时注入,你只需要返回一个实现了Servicetrait 的 router。在 services/shuttle-axum/src/lib.rs 中可以看到,AxumService通过实现shuttle_runtime::Service::bind,在运行时传入的SocketAddr上启动axum::serve,ShuttleAxum就是Result<AxumService, Error>的类型别名。
再加一步:一行代码拿到共享 Postgres 数据库
继续增强:通过#[shuttle_shared_db::Postgres]属性注解,把sqlx::PgPool直接声明为main函数的参数(README.md):
use axum::{routing::get, Router}; async fn hello_world() -> &'static str { "Hello, world!" } #[shuttle_runtime::main] async fn main( #[shuttle_shared_db::Postgres] pool: sqlx::PgPool, ) -> shuttle_axum::ShuttleAxum { pool.execute(include_str!("../schema.sql")) .await .expect("failed to run migrations"); let router = Router::new().route("/", get(hello_world)); Ok(router.into()) }再次运行shuttle deploy,你的应用就带着一个开箱即用、连接就绪的数据库上线了。这就是 Shuttle "One-line Resource Provisioning" 的直观体现:资源以函数参数的形式注入,供给、连接串、权限配置全部由平台接管,无需手写任何云服务商配置。
深入原理:#[shuttle_runtime::main] 宏做了什么
#[shuttle_runtime::main]是 shuttle-codegen crate 提供的过程宏,入口实现位于 codegen/src/shuttle_main.rs。它会把你写的main函数改造成三部分:
- 真实入口
fn main():手动展开#[tokio::main]——创建一个多线程 Tokio runtime 并block_on内部的启动流程(codegen/src/shuttle_main.rs); __loader:拿到ResourceFactory,逐个调用各资源属性对应的ResourceInputBuilder::build()构造资源请求,序列化后交给运行时(codegen/src/shuttle_main.rs);__runner:在资源就绪后,把供给结果反序列化、通过into_resource()转成你声明的类型(如sqlx::PgPool),再调用你原来写的main函数(宏里已被改名为__shuttle_main)(codegen/src/shuttle_main.rs)。
宏还会做两项重要检查:
- 返回值校验:
#[shuttle_runtime::main]函数必须返回一个受支持的 service 类型(ShuttleAxum、ShuttleRocket等),否则编译报错并提示参考文档(codegen/src/shuttle_main.rs)。仓库的编译器测试用例见 codegen/tests/compiler_output/missing-return.rs; - 参数属性解析:如果参数缺少
#[shuttle_*]属性,宏会直接报错,提示"Try adding an attribute like#[shuttle_shared_db::Postgres]"(codegen/src/shuttle_main.rs)。
此外,资源属性中的字符串字面量支持{secrets.xxx}占位符插值——宏会把factory.get_secrets()中的 secret 注入到资源配置串中(如连接串里的密码),例如sensitive = "user:{secrets.password}"(codegen/src/shuttle_main.rs)。
运行时四阶段:Loading / Provisioning / Init / Running
部署环境下,shuttle-runtime 的启动流程定义在 runtime/src/rt.rs,分为四个阶段:
| 阶段 | 行为 | 失败退出码 |
|---|---|---|
| Loading(加载) | 从 API 拉取项目 secrets,构建ResourceFactory,执行__loader生成资源请求 | 101 / 111 |
| Provisioning(供给) | 逐个调用provision_resourceAPI,轮询资源状态(Provisioning/Authorizing时每 2 秒重试),直到Ready | 121 / 131 / 132 |
| Resource Init(初始化) | 执行__runner,把资源供给结果转换为函数参数并调用用户代码 | 151 |
| Running(运行) | 调用service.bind(addr)启动服务,同时监听 SIGTERM/SIGINT(Unix)或 Ctrl-C/Ctrl-Break(Windows)优雅退出 | 1 / 10 |
在部署态下,运行时还会在资源供给完成后通知 sidecar 关闭(请求/__shuttle/shutdown),并在可选的SHUTTLE_HEALTHZ_PORT上启动一个轻量 HTTP health check 服务(runtime/src/rt.rs)。启动前的环境检查(SHUTTLE_ENV必须存在、拒绝旧的--port参数)与 tracing 初始化见 runtime/src/start.rs。
Secrets 管理:Secrets.toml
本地/部署用 secrets 通过Secrets.toml提供,格式是简单的 TOML 键值对:
DATABASE_PASSWORD = 's3cr3t' API_TOKEN = 'tok_xxx'- 本地运行(
shuttle run)时,CLI 会优先读取Secrets.dev.toml,其次Secrets.toml;部署(shuttle deploy)时只读取Secrets.toml(见 cargo-shuttle/src/lib.rs); - 部署时 secrets 会随部署请求一起上传,供运行时供给资源、注入到
ResourceFactory中; - 运行时以
Secret<T>包装类型管理 secret,Debug/Display输出会被替换为[REDACTED ...],值在Drop时会被清零(zeroize)以防止内存泄露(见 common/src/secrets.rs); shuttle init生成的.gitignore会自动包含Secrets*.toml,避免 secrets 被误提交(见 cargo-shuttle/src/init.rs)。
项目配置:Shuttle.toml
在项目根目录的Shuttle.toml中可以按需配置项目级行为(schema 定义见 cargo-shuttle/src/config.rs):
# 部署时额外包含被忽略的文件(支持 glob 模式) [deploy] include = ["assets/**", "config/*.json"] # 存在未提交改动时拒绝部署(可用 --allow-dirty 覆盖) deny_dirty = true # 构建产物中需要复制到运行容器的文件(服务运行所需,如模板、静态资源) [build] assets = ["templates/**"]注意:Shuttle.toml首字母大写,小写的shuttle.toml会被检测并给出警告提示(cargo-shuttle/src/config.rs)。项目与平台的关联 ID 则记录在内部文件.shuttle/config.toml中(id字段),由shuttle project link/init/deploy自动维护。
常用 CLI 命令速查
除init、run、deploy外,shuttle还提供完整的项目管理能力(命令清单见 cargo-shuttle/src/args.rs):
| 命令 | 别名 | 作用 |
|---|---|---|
shuttle project create --name <n> | proj start | 在平台创建项目 |
shuttle project list | proj ls | 列出你有权限访问的项目 |
shuttle project status | proj stat | 查看当前项目状态 |
shuttle project link | proj | 将当前工作区关联到某个项目 |
shuttle project delete | proj rm | 删除项目(连同数据库、secrets、自定义域名) |
shuttle deployment list | depl ls | 分页列出服务的部署记录 |
shuttle deployment status [ID] | depl stat | 查看某次部署状态 |
shuttle deployment redeploy [ID] | depl | 重新部署历史版本 |
shuttle deployment stop | depl | 停止当前运行中的部署 |
shuttle logs | — | 查看当前部署日志(--latest查看最近一次部署) |
shuttle resource list | res ls | 列出项目资源(--show-secrets显示连接串等敏感值) |
shuttle resource delete <type> | res rm | 删除某类资源(如database::shared::postgres) |
shuttle certificate add <domain> | cert | 为自定义域名添加 SSL 证书 |
shuttle account | acc | 查看账号信息 |
shuttle logout | — | 退出登录(--reset-api-key同时重置 API key) |
shuttle upgrade | — | 升级 CLI(--preview安装 main 分支的未发布版本) |
全局选项适用于所有子命令(见 cargo-shuttle/src/args.rs):--wd/--working-directory <path>(指定工作目录)、--name、--id、--output json|normal、--debug、--offline、--api-url <url>(自定义 API 地址)等。
官方维护的周边仓库
Shuttle 生态由多个仓库构成(README.md):
| 仓库 | 说明 |
|---|---|
| shuttle(本仓库) | 所有库 crate 与 Shuttle CLI |
| shuttle-examples | 官方维护、可直接部署到 Shuttle 的示例项目 |
| shuttle-docs | 托管在 docs.shuttle.dev 的完整文档 |
| www | 官网与博客 |
| deploy-action | 用于持续部署的 GitHub Action |
| awesome-shuttle | 由社区维护的 Shuttle 托管项目资源清单 |
| shuttlings | 一套 Rust 编码挑战,是上手 Rust + Shuttle 的绝佳练习 |
支持的框架与自定义集成
services/目录下的 crate 提供了官方的一等(first-class)框架集成,返回类型对应关系如下(见 codegen/src/lib.rs):
| 返回类型 | crate | 框架 |
|---|---|---|
ShuttleAxum | shuttle-axum | axum(默认 0.8,通过axum-0-7feature 支持 0.7) |
ShuttleActixWeb | shuttle-actix-web | actix-web |
ShuttleRocket | shuttle-rocket | rocket |
ShuttleSalvo | shuttle-salvo | salvo |
ShuttlePoem | shuttle-poem | poem |
ShuttleRama | shuttle-rama | rama |
ShuttleSerenity | shuttle-serenity | serenity / poise(Discord Bot) |
ShuttleTower | shuttle-tower | tower |
ShuttleWarp | shuttle-warp | warp |
如果现有框架不在列表中,你也可以自行实现集成:只需为你的框架实现shuttle_service::Servicetrait(核心是async fn bind(self, addr: SocketAddr) -> Result<(), Error>),详见 services/README.md。
进一步阅读
- 开发本仓库请参考 DEVELOPING.md,参与贡献请阅读 CONTRIBUTING.md;
- 框架集成的完整文档入口:services/README.md 与各 crate 自带的 README(如 services/shuttle-axum/README.md);
- 运行时的更多细节:runtime/README.md;
- 部署模型的类型定义(
DeploymentRequest、BuildArgs、BuildMeta等):common/src/models/deployment.rs; - CLI 集成测试(覆盖工作目录不存在、项目 ID 缺失等边界场景):cargo-shuttle/tests/integration/main.rs。
至此,你已经走通了 Shuttle 的完整主线:安装 CLI → 登录 → 用模板初始化 → 本地验证 → 一键部署,并理解了#[shuttle_runtime::main]、资源供给四阶段与 secrets/配置机制。下一步建议基于官方shuttle-examples挑选你熟悉的框架示例,把"一行代码拿数据库"的模式应用到真实业务中。
- 云原生
- 后端
- DevOps
【免费下载链接】shuttle
Build & ship backends without writing any infrastructure files.
相关推荐
50个精选 recipes:用Google Workspace CLI实现办公自动化
50个精选 recipes:用Google Workspace CLI实现办公自动化 Google Workspace CLI是一款强大的命令行工具,能够帮助用
Shuttle项目部署指南:从源码到可执行应用的完整流程
Shuttle项目部署指南:从源码到可执行应用的完整流程 🚀 终极指南:如何快速构建macOS快捷菜单工具Shuttle Shuttle是一款专为macOS设
桌面应用开发工具使用 shuttle-actix-web 在 Shuttle 上部署 Actix Web 应用
使用 shuttle actix web 在 Shuttle 上部署 Actix Web 应用 导读 shuttle actix web https://lin
云原生后端DevOps
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考