部署 Rust 应用程序
Zeabur 原则上支持所有类型的 Rust 应用程序——默认情况下会自动查找运行文件;如果项目有多个运行文件,也可以在“Service 名称”一栏(或者是使用 ZBPACK_RUST_ENTRY
)自行指定要运行的文件名称。
如果你手边没有项目,可以 fork zeabur/axum-template 仓库到你的 GitHub 账户,然后在 Zeabur 上试着部署。
支持的项目类型
- 单运行文件项目:即运行文件只有
src/main.rs
一个入口的 Rust 项目。Zeabur 会自动查找cargo install
之后的产出的第一个运行文件。 - 多运行文件项目:如果除了
src/main.rs
,项目在src/bin
也有其他运行文件,请在“Service 名称”一栏填写“你想运行的最终产物的名称”,或者是在zbpack.json
填写这个设置你也可以使用环境变量{ "rust": { "entry": "your-entry" } }
ZBPACK_RUST_ENTRY
达到同样的效果。 - Cargo Workspace monorepo:如果你的项目是由多个 crate 组成,请在“Service 名称”一栏填写“你想运行的最终产物的名称”。默认情况下会
cargo install
workspace 下的 所有项目,你除了可以通过上述ZBPACK_RUST_ENTRY
的方式指定运行文件名称外,也可以在zbpack.json
直接指定这个应用程序 workspace 所在的位置。 如果你的应用程序在 Repository 根目录的rest-api
文件夹下,你可以这样填写:你也可以使用环境变量{ "rust": { "app_dir": "rest-api" } }
ZBPACK_RUST_APP_DIR
达到同样的效果。
如果你填写的运行文件不存在,则会改用自动查找的形式。“自动查找”会查找编译出的所有运行文件,并运行找到的第一个文件。因为这种模式在多项目情况下很容易猜错,因此在复杂的项目场景下(如第二和第三点提到的多运行文件项目),建议你根据〈查找最终产物名称〉的方式填写正确的“Service 名称”。
查找最终产物名称
最终产物可以在你项目的 target/release
中找到。具体查找的方式:
-
你需要 Rust toolchain 才能编译项目,可到 Rust 官方网站 下载。
-
clone 你要部署的项目,并且进到项目目录。
-
运行
cargo build --release
编译项目。$ cargo run --release Compiling zeabur v0.1.0 (/project) Finished release [optimized] target(s) in 0.65s Running `target/release/zeabur`
-
找到 Running
target/release/zeabur
那一行,提取最后的运行文件名称 (zeabur) 即可 -
在 Service 名称或
ZBPACK_RUST_ENTRY
填入zeabur
。
設定的最终产物最后会被命名为 /app/main
。
复制其他文件
如果你除了运行文件之外,还依赖代码库的其他文件。举例来说:
*
|`-- public <-- 你的程序依赖这个文件夹
|`-- src
| `-- main.rs
|`-- Cargo.toml
|`-- Cargo.lock
`--- config.toml <-- 你的程序依赖这个文件
你可以在 zbpack.json
中填写 rust.assets
,里面填入你想保留的文件夹或文件,文件夹可以选择用 /
结尾。范例如下:
{
"rust": {
"assets": [
"public/",
"config.toml"
]
}
}
自定义编译和启动命令
Zeabur 在 Rust 中提供了「编译命令」、「启动命令」和「启动前命令」,方便你在 Rust 项目的各个构建阶段插入所需的依赖、写入必要的文件。
编译命令
你可以使用 ZBPACK_BUILD_COMMAND
指定 编译前要运行的命令,例如:
ZBPACK_BUILD_COMMAND=apt update && apt install -y sqlite3 && rm -rf /var/lib/apt/lists/*
也可以使用 zbpack.json
指定:
{
"build_command": "apt update && apt install -y sqlite3 && rm -rf /var/lib/apt/lists/*"
}
启动命令
你可以使用 ZBPACK_START_COMMAND
覆盖 Zeabur 默认指定的启动命令,例如:
ZBPACK_START_COMMAND="/app/main --debug"
也可以使用 zbpack.json
指定:
{
"start_command": "/app/main --debug"
}
启动前命令
如果你需要在启动前安装一些依赖,可以使用 ZBPACK_PRE_START_COMMAND
指定要在启动前运行的命令:
ZBPACK_PRE_START_COMMAND="apt update && apt install -y sqlite3 && rm -rf /var/lib/apt/lists/*"
也可以使用 zbpack.json
指定:
{
"pre_start_command": "apt update && apt install -y sqlite3 && rm -rf /var/lib/apt/lists/*"
}
与 ZBPACK_START_COMMAND
相比,它会持久运行的内容,不会在每次重新启动时重新执行,从而提高速度。
自动安装依赖
如果你的项目依赖 OpenSSL 且有在 Cargo.toml
中显式依赖(或 Cargo.lock
间接依赖)openssl
,Zeabur 会自动安装 openssl
运行时库。
运行环境
Zeabur 目前使用 rust:1-silm
作为运行镜像。你的运行文件会放在 /app
目录,并将 /
(根目录)作为运行目录。
rust.assets
中的文件会放在 /app
目录下,即与可运行文件在同一目录。如果你有读取 assets 的需求,通常实务上会从 相对于可运行文件的路径 读取文件。如下例子会获取你 images
资源的所在位置。
use std::env;
use std::path::Path;
fn main() {
let exe_path = env::current_exe().expect("Failed to get current executable path");
let exe_dir = exe_path.parent().expect("Failed to get executable directory");
let relative_path = exe_dir.join("images");
println!("config.toml path: {:?}", relative_path);
}
注意,如果是配置文件,实务上通常从运行目录获取。考虑到运行目录是根目录,在使用 Config Editor 新增配置文件时,请填写 /config.toml
(而不是 /app/config.toml
),然后从运行目录读取文件:
use std::env;
use std::fs::File;
use std::io::{self, Read};
use std::path::PathBuf;
fn main() -> io::Result<()> {
let current_dir = env::current_dir()?;
let config_path: PathBuf = current_dir.join("config.toml");
// 这里推荐使用 serde 进行反序列化。这里只是为了演示所以使用 read_to_string。
let mut file = File::open(config_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("Config file contents:\n{}", contents);
Ok(())
}
Serverless 部署
不同于其他 PaaS 平台是直接将你的 Rust 应用程序打包在 Docker 容器中运行,Zeabur 同时支持使用 Serverless 部署 Rust 的方式,这可以让你的 Rust 应用程序只有在收到请求的时候才启动,而不是像容器一样一直运行,浪费资源。
如果想要用 Serverless 部署 Rust 应用程序,请在环境变量中加入 ZBPACK_SERVERLESS=1
。