feat(gitea): 添加 Dockerfile 模板和 Rust 支持,优化 runner 网络配置说明

- 新增 Go、Node.js、Rust 服务的 Dockerfile 模板
- 新增 Rust 快速参考指南
- 新增 Rust 后端工作流模板
- 优化 create-runner.md,明确 host 网络模式为缓存必需条件
- 更新 gitea skill 主文档
This commit is contained in:
voson
2026-01-30 10:11:18 +08:00
parent f36b0159bd
commit 425ca5b5fd
8 changed files with 3111 additions and 288 deletions

View File

@@ -0,0 +1,443 @@
# Rust 项目 Gitea CI/CD 快速参考
快速设置 Rust 项目的 CI/CD 流程。
## 最小化配置3 步)
### 1. 创建 Dockerfile.ci
在项目根目录创建 `Dockerfile.ci`
```dockerfile
FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata curl && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
WORKDIR /app
COPY your-binary-name .
ENV TZ=Asia/Shanghai
ENV RUST_LOG=info
EXPOSE 9090
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -sf http://localhost:9090/healthz || exit 1
CMD ["./your-binary-name"]
```
**修改项**
- `your-binary-name` → 你的二进制文件名(通常和 `Cargo.toml` 中的 `name` 一致)
- `9090` → 你的服务端口
### 2. 创建 workflow 文件
创建 `.gitea/workflows/your-service.yml`
```yaml
name: Your Service - Build & Publish
on:
push:
paths:
- '**' # 修改为实际监听路径
tags:
- 'v*' # 修改为实际 tag 格式
env:
SERVICE_PREFIX: your-service # 修改为实际服务名
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_DIST_SERVER: https://rsproxy.cn
RUSTUP_UPDATE_ROOT: https://rsproxy.cn/rustup
jobs:
build-and-publish:
runs-on: ubuntu-latest # 修改为你的 Runner 标签
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: |
curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh -s -- -y
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
source "$HOME/.cargo/env"
rustup target add x86_64-unknown-linux-musl
- name: Build
run: |
cargo build --release --target x86_64-unknown-linux-musl
cp target/x86_64-unknown-linux-musl/release/your-binary-name .
- name: Docker Login
uses: docker/login-action@v3
with:
registry: ${{ github.server_url }}
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.RELEASE_TOKEN }}
- name: Build & Push Image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.ci
push: true
tags: |
${{ github.server_url }}/${{ github.repository }}:latest
${{ github.server_url }}/${{ github.repository }}:${{ github.sha }}
```
**修改项**
- `your-service` → 你的服务名
- `your-binary-name` → 你的二进制文件名
- `ubuntu-latest` → 你的 Runner 标签
- `paths` → 触发构建的路径
- `tags` → 触发构建的 tag 格式
### 3. 推送代码并打 tag
```bash
git add .gitea Dockerfile.ci
git commit -m "ci: 添加 CI/CD 配置"
git push
# 触发构建
git tag v0.1.0
git push origin v0.1.0
```
## 进阶配置
### 添加交叉编译支持
如果你的 Runner 是 ARM64但需要构建 x86_64 镜像:
```yaml
- name: Install Zig and cargo-zigbuild
run: |
wget -q https://ziglang.org/download/0.13.0/zig-linux-aarch64-0.13.0.tar.xz
tar -xf zig-linux-aarch64-0.13.0.tar.xz
mv zig-linux-aarch64-0.13.0 /opt/zig
echo "/opt/zig" >> $GITHUB_PATH
cargo install cargo-zigbuild
- name: Build
run: |
cargo zigbuild --release --target x86_64-unknown-linux-musl
```
### 添加 Rust 缓存
```yaml
- name: Cache Rust dependencies
uses: https://github.com/Swatinem/rust-cache@v2
with:
workspaces: . -> target
cache-targets: true
```
### 添加版本号注入
**1. 创建 `build.rs`**
```rust
fn main() {
if let Ok(git_tag) = std::env::var("GIT_TAG") {
println!("cargo:rustc-env=GIT_TAG={}", git_tag);
}
println!("cargo:rerun-if-env-changed=GIT_TAG");
}
```
**2. 在 workflow 中设置环境变量**
```yaml
- name: Build
env:
GIT_TAG: ${{ github.ref_name }}
run: cargo build --release
```
**3. 在代码中使用**
```rust
let version = option_env!("GIT_TAG").unwrap_or("dev");
println!("Version: {}", version);
```
### 添加 Release 创建
```yaml
release:
name: Create Release
runs-on: ubuntu-latest
needs: build-and-publish
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Create Release
run: |
curl -X POST "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases" \
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{
\"tag_name\": \"${{ github.ref_name }}\",
\"name\": \"Release ${{ github.ref_name }}\",
\"body\": \"自动构建的 Release\"
}"
```
## 健康检查端点实现
如果你的服务还没有健康检查端点,快速添加:
### 使用 Axum
```rust
use axum::{Router, routing::get};
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/healthz", get(|| async { "OK" }));
let listener = tokio::net::TcpListener::bind("0.0.0.0:9090")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
```
### 使用 Actix-web
```rust
use actix_web::{web, App, HttpServer, HttpResponse};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/healthz", web::get().to(|| async { HttpResponse::Ok().body("OK") }))
})
.bind("0.0.0.0:9090")?
.run()
.await
}
```
### 使用 Rocket
```rust
#[macro_use] extern crate rocket;
#[get("/healthz")]
fn healthz() -> &'static str {
"OK"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![healthz])
}
```
## Cargo.toml 优化配置
```toml
[profile.release]
opt-level = 3 # 最高优化级别
lto = true # 链接时优化
codegen-units = 1 # 单个代码生成单元
strip = true # 去除符号表
panic = 'abort' # panic 时直接退出
```
## .dockerignore 示例
创建 `.dockerignore` 减小构建上下文:
```
target/
.git/
.gitignore
*.md
tests/
benches/
examples/
.github/
.gitea/workflows/
Dockerfile*
docker-compose.yml
```
## 环境变量配置
### 在 workflow 中
```yaml
env:
RUST_LOG: info # 日志级别
CONFIG_FILE: production.yaml # 配置文件
DATABASE_URL: ${{ secrets.DATABASE_URL }} # 数据库连接
```
### 在 Dockerfile 中
```dockerfile
ENV RUST_LOG=info
ENV CONFIG_FILE=production.yaml
```
### 在运行时
```bash
docker run -e RUST_LOG=debug -e CONFIG_FILE=custom.yaml your-image
```
## 常见 Runner 标签
| 标签 | 说明 |
|------|------|
| `ubuntu-latest` | Ubuntu 最新版本 |
| `darwin-arm64` | macOS ARM64 |
| `darwin-amd64` | macOS x86_64 |
| `linux-amd64` | Linux x86_64 |
| `linux-arm64` | Linux ARM64 |
查看可用 Runner
```bash
/gitea-list-runners
```
## 触发条件参考
### 推送到特定分支
```yaml
on:
push:
branches:
- main
- develop
```
### 推送特定路径
```yaml
on:
push:
paths:
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
```
### 特定 tag 格式
```yaml
on:
push:
tags:
- 'v*' # v1.0.0, v2.1.3
- 'device-rs-*' # device-rs-1.0.0
```
### Pull Request
```yaml
on:
pull_request:
branches:
- main
```
### 定时触发
```yaml
on:
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点
```
## 调试技巧
### 查看 workflow 日志
在 Gitea 仓库页面:
1. 点击 "Actions"
2. 选择对应的 workflow run
3. 查看每个 step 的日志
### 本地测试构建
```bash
# 测试 Rust 构建
cargo build --release --target x86_64-unknown-linux-musl
# 测试 Docker 构建
docker build -f Dockerfile.ci -t test:latest .
# 测试容器运行
docker run -p 9090:9090 test:latest
```
### 使用 act 本地运行 workflow
```bash
# 安装 act如果使用 Gitea Actions
# 注意act 主要支持 GitHub ActionsGitea Actions 可能有兼容性问题
# 列出可用的 actions
act -l
# 运行特定 job
act -j build-and-publish
```
## 完整配置示例
参考 BMS 项目的 device-rs
- Workflow: [device-rs.yml](https://git.voson.top/tianchu/bms/src/branch/main/.gitea/workflows/device-rs.yml)
- Dockerfile: [Dockerfile.ci](https://git.voson.top/tianchu/bms/src/branch/main/device-rs/Dockerfile.ci)
- 项目结构: [device-rs/](https://git.voson.top/tianchu/bms/src/branch/main/device-rs)
## 故障排查清单
### 构建失败
- [ ] 检查 Rust 版本是否满足要求
- [ ] 检查依赖是否正确(`Cargo.lock` 是否提交)
- [ ] 检查 musl 目标是否安装(`rustup target list --installed`
- [ ] 查看完整构建日志
### Docker 推送失败
- [ ] 检查 Docker Registry 地址是否正确
- [ ] 检查 `REGISTRY_USERNAME` 变量是否设置
- [ ] 检查 `RELEASE_TOKEN` secret 是否正确
- [ ] 检查 Token 权限(需要 packages write 权限)
### 容器启动失败
- [ ] 检查二进制文件名是否正确
- [ ] 检查端口是否正确
- [ ] 检查健康检查端点是否存在
- [ ] 查看容器日志(`docker logs <container>`
### Runner 无法连接
- [ ] 检查 Runner 是否在运行(`/gitea-list-runners`
- [ ] 检查 Runner labels 是否匹配 workflow 中的 `runs-on`
- [ ] 检查网络连接
- [ ] 查看 Runner 日志(`~/.config/gitea/runners/<runner-name>/*.log`
## 更多资源
- [完整 Workflow 模板](./workflow-templates/rust-backend.md)
- [Dockerfile 模板详解](./dockerfile-templates/rust-service.md)
- [Gitea Actions 文档](https://docs.gitea.com/usage/actions/quickstart)
- [Rust CI 最佳实践](https://doc.rust-lang.org/cargo/guide/continuous-integration.html)