news 2026/10/15 17:41:10

Shuttle 入门指南:用一行代码为 Rust 应用供给资源并一键部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Shuttle 入门指南:用一行代码为 Rust 应用供给资源并一键部署
  • 云原生
  • 后端
  • DevOps

【免费下载链接】shuttle

Build & ship backends without writing any infrastructure files.

项目地址:https://gitcode.com/gh_mirrors/sh/shuttle
点击查看免费下载

本文以 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 login

login命令默认走设备授权流程(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中看到:

  1. 将模板克隆到临时目录(gix浅克隆,等价于git clone --depth 1);
  2. 把Cargo.toml中的 crate 名改写为你的项目名;如果是 workspace 结构则改写在Shuttle.toml的name字段中;
  3. 在.gitignore(或--no-git时的.ignore)中补充/target、.shuttle*、Secrets*.toml等推荐忽略规则(见 cargo-shuttle/src/init.rs);
  4. 将模板文件拷贝到目标目录(跳过target与.git目录);
  5. 若无现成 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函数改造成三部分:

  1. 真实入口fn main():手动展开#[tokio::main]——创建一个多线程 Tokio runtime 并block_on内部的启动流程(codegen/src/shuttle_main.rs);
  2. __loader:拿到ResourceFactory,逐个调用各资源属性对应的ResourceInputBuilder::build()构造资源请求,序列化后交给运行时(codegen/src/shuttle_main.rs);
  3. __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 秒重试),直到Ready121 / 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 listproj ls列出你有权限访问的项目
shuttle project statusproj stat查看当前项目状态
shuttle project linkproj将当前工作区关联到某个项目
shuttle project deleteproj rm删除项目(连同数据库、secrets、自定义域名)
shuttle deployment listdepl ls分页列出服务的部署记录
shuttle deployment status [ID]depl stat查看某次部署状态
shuttle deployment redeploy [ID]depl重新部署历史版本
shuttle deployment stopdepl停止当前运行中的部署
shuttle logs—查看当前部署日志(--latest查看最近一次部署)
shuttle resource listres ls列出项目资源(--show-secrets显示连接串等敏感值)
shuttle resource delete <type>res rm删除某类资源(如database::shared::postgres)
shuttle certificate add <domain>cert为自定义域名添加 SSL 证书
shuttle accountacc查看账号信息
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框架
ShuttleAxumshuttle-axumaxum(默认 0.8,通过axum-0-7feature 支持 0.7)
ShuttleActixWebshuttle-actix-webactix-web
ShuttleRocketshuttle-rocketrocket
ShuttleSalvoshuttle-salvosalvo
ShuttlePoemshuttle-poempoem
ShuttleRamashuttle-ramarama
ShuttleSerenityshuttle-serenityserenity / poise(Discord Bot)
ShuttleTowershuttle-towertower
ShuttleWarpshuttle-warpwarp

如果现有框架不在列表中,你也可以自行实现集成:只需为你的框架实现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.

项目地址:https://gitcode.com/gh_mirrors/sh/shuttle
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 17:41:09

华为云 ECS 的 SSH 安全组如何收口:先验证新入口,再撤掉 0.0.0.0/0

检查华为云 ECS 时&#xff0c;如果发现入站规则允许 0.0.0.0/0 访问 TCP 22&#xff0c;意味着任意 IPv4 来源都可以尝试连接 SSH。直接删除这条规则看似简单&#xff0c;却可能把运维人员一起挡在外面。更稳妥的做法是&#xff1a;先确认实际出口 IP 和应急登录方式&#xff…

作者头像 李华
网站建设 2026/10/15 17:40:49

PHP客服系统接入AI知识库的轻量级实现方案

简介&#xff1a;这是一套基于ThinkPHP框架开发的PHP在线客服系统源码&#xff0c;面向Web开发者与企业技术团队&#xff0c;解决传统客服响应慢、知识检索效率低的问题&#xff0c;通过接入AI知识库实现智能问答与工单辅助。资源包共2010个文件&#xff0c;涵盖368个HTML页面&…

作者头像 李华
网站建设 2026/10/15 17:40:45

导数的本质:从瞬时变化率到工程中的局部线性逼近

1. 这不是公式默写&#xff0c;是重新理解“变化率”的起点 你翻开微积分教材&#xff0c;第一页写着“导数是函数在某点的瞬时变化率”&#xff0c;接着就是一堆极限定义、求导法则、链式法则……然后你开始背&#xff1a;sin x 的导数是 cos x&#xff0c;e^x 的导数还是 e^x…

作者头像 李华
网站建设 2026/10/15 17:40:17

二维矩阵最小覆盖子矩阵:KMP求周期与LCM合并的巧妙解法

先说结论&#xff1a;这道题真正考的不是二维KMP&#xff0c;而是“能不能把二维平铺问题拆成一维周期问题”的抽象能力。我最初拿到“奶牛矩阵 / Milking Grid”这个题目时&#xff0c;第一反应是去找二维KMP模板&#xff0c;结果整个思路被带偏了。后来冷静下来把题意转换成“…

作者头像 李华
网站建设 2026/10/15 17:40:04

淘宝商品页用户行为信号采集与分析实战

1. 这不是“爬虫教程”&#xff0c;而是一次真实的电商行为数据解剖实验我去年接手过一个模拟项目X&#xff0c;目标很朴素&#xff1a;不碰任何接口权限、不调用官方SDK、不依赖第三方数据平台&#xff0c;仅用公开可得的网页结构信息&#xff0c;对淘宝系商品页的用户行为链路…

作者头像 李华