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,571 @@
# Rust 服务 Dockerfile 模板
Rust 项目的 Docker 容器化模板,支持多种构建场景。
## 模板类型
### 1. CI 构建镜像Dockerfile.ci
**适用场景**:在 CI/CD 中使用,二进制文件已在外部构建完成。
**优点**
- 镜像体积最小(~20MB
- 构建速度快
- 适合生产环境
```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
# 复制编译好的二进制文件(由 CI workflow 构建)
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"]
```
**使用说明**
1.`your-binary-name` 替换为实际的二进制文件名
2. 修改 `EXPOSE` 端口号
3. 修改 `HEALTHCHECK` 的端点和端口
4. 在 CI workflow 中先构建二进制,再构建镜像
### 2. 完整构建镜像Dockerfile
**适用场景**:本地开发、无 CI 环境、独立构建。
**优点**
- 自包含构建流程
- 可在任何环境构建
- 利用 Docker 缓存加速
```dockerfile
# ============================================
# 构建阶段
# ============================================
FROM rust:1.83-alpine AS builder
# 安装构建依赖
# musl-dev: musl libc 开发包(静态链接)
# openssl-dev: OpenSSL 开发包(如果项目依赖 openssl
# pkgconfig: pkg-config 工具
RUN apk add --no-cache musl-dev openssl-dev pkgconfig
# 配置 Cargo 镜像加速(使用 rsproxy.cn
RUN mkdir -p /root/.cargo && \
echo '[source.crates-io]' > /root/.cargo/config.toml && \
echo 'replace-with = "rsproxy-sparse"' >> /root/.cargo/config.toml && \
echo '[source.rsproxy-sparse]' >> /root/.cargo/config.toml && \
echo 'registry = "sparse+https://rsproxy.cn/index/"' >> /root/.cargo/config.toml
WORKDIR /build
# 先复制依赖文件,利用 Docker 层缓存
# 只要 Cargo.toml 和 Cargo.lock 不变,依赖层就会被缓存
COPY Cargo.toml Cargo.lock ./
# 创建虚拟 src 目录,预先下载和编译依赖
# 这样修改源码时不需要重新编译依赖
RUN mkdir src && \
echo "fn main() {}" > src/main.rs && \
cargo build --release --target x86_64-unknown-linux-musl && \
rm -rf src
# 复制实际源码
COPY src ./src
# 构建 Release 版本musl 静态链接)
RUN cargo build --release --target x86_64-unknown-linux-musl
# ============================================
# 运行阶段
# ============================================
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 --from=builder /build/target/x86_64-unknown-linux-musl/release/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"]
```
**使用说明**
1.`your-binary-name` 替换为 `Cargo.toml` 中的 `[[bin]]` name
2. 如果不需要 OpenSSL可移除 `openssl-dev`
3. 修改端口和健康检查配置
### 3. 依赖缓存优化版Dockerfile.cache
**适用场景**:本地开发,频繁构建。
**优点**
- 最大化利用缓存
- 依赖只编译一次
- 适合迭代开发
```dockerfile
# ============================================
# 依赖缓存阶段
# ============================================
FROM rust:1.83-alpine AS dependencies
RUN apk add --no-cache musl-dev openssl-dev pkgconfig
# 配置 Cargo 镜像
RUN mkdir -p /root/.cargo && \
echo '[source.crates-io]' > /root/.cargo/config.toml && \
echo 'replace-with = "rsproxy-sparse"' >> /root/.cargo/config.toml && \
echo '[source.rsproxy-sparse]' >> /root/.cargo/config.toml && \
echo 'registry = "sparse+https://rsproxy.cn/index/"' >> /root/.cargo/config.toml
WORKDIR /build
# 只复制依赖文件
COPY Cargo.toml Cargo.lock ./
# 创建虚拟 main.rs编译依赖
RUN mkdir -p src && \
echo "fn main() {}" > src/main.rs && \
cargo build --release --target x86_64-unknown-linux-musl
# 删除虚拟源码编译产物
RUN rm -f target/x86_64-unknown-linux-musl/release/deps/your_binary_name*
# ============================================
# 构建阶段
# ============================================
FROM rust:1.83-alpine AS builder
RUN apk add --no-cache musl-dev openssl-dev pkgconfig
WORKDIR /build
# 从依赖阶段复制编译缓存
COPY --from=dependencies /root/.cargo /root/.cargo
COPY --from=dependencies /build/target target
# 复制所有文件
COPY . .
# 构建项目
RUN cargo build --release --target x86_64-unknown-linux-musl
# ============================================
# 运行阶段
# ============================================
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 --from=builder /build/target/x86_64-unknown-linux-musl/release/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"]
```
**使用说明**
1.`your_binary_name` 替换为二进制文件名(下划线形式)
2. 适合本地 `docker build` 使用
### 4. 多平台构建版Dockerfile.multiarch
**适用场景**:需要支持 ARM64 和 AMD64。
```dockerfile
# ============================================
# 构建阶段(支持多平台)
# ============================================
FROM --platform=$BUILDPLATFORM rust:1.83-alpine AS builder
# 安装构建依赖
RUN apk add --no-cache musl-dev openssl-dev pkgconfig clang
# 配置 Cargo 镜像
RUN mkdir -p /root/.cargo && \
echo '[source.crates-io]' > /root/.cargo/config.toml && \
echo 'replace-with = "rsproxy-sparse"' >> /root/.cargo/config.toml && \
echo '[source.rsproxy-sparse]' >> /root/.cargo/config.toml && \
echo 'registry = "sparse+https://rsproxy.cn/index/"' >> /root/.cargo/config.toml
# 安装目标架构支持
ARG TARGETARCH
RUN case "$TARGETARCH" in \
"amd64") echo "x86_64-unknown-linux-musl" > /target.txt ;; \
"arm64") echo "aarch64-unknown-linux-musl" > /target.txt ;; \
*) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; \
esac && \
rustup target add $(cat /target.txt)
WORKDIR /build
COPY Cargo.toml Cargo.lock ./
COPY src ./src
# 构建对应架构
RUN cargo build --release --target $(cat /target.txt)
# 复制二进制到统一路径
RUN mkdir -p /app && \
cp target/$(cat /target.txt)/release/your-binary-name /app/
# ============================================
# 运行阶段
# ============================================
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 --from=builder /app/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"]
```
**使用说明**
```bash
# 构建多平台镜像
docker buildx build --platform linux/amd64,linux/arm64 -t your-image:latest .
```
## 高级配置
### 健康检查配置
```dockerfile
# 存活探针Liveness Probe
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -sf http://localhost:9090/healthz || exit 1
# 参数说明:
# --interval=30s 每 30 秒检查一次
# --timeout=5s 单次检查超时 5 秒
# --start-period=10s 容器启动后 10 秒开始检查
# --retries=3 失败 3 次后认为不健康
```
### 多端点健康检查
```dockerfile
# 使用脚本检查多个端点
RUN echo '#!/bin/sh' > /healthcheck.sh && \
echo 'curl -sf http://localhost:9090/healthz || exit 1' >> /healthcheck.sh && \
echo 'curl -sf http://localhost:9090/readyz || exit 1' >> /healthcheck.sh && \
chmod +x /healthcheck.sh
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD ["/healthcheck.sh"]
```
### 环境变量配置
```dockerfile
# 基础环境变量
ENV TZ=Asia/Shanghai
ENV RUST_LOG=info
ENV RUST_BACKTRACE=1
# 应用配置(可在 docker run 时覆盖)
ENV CONFIG_FILE=production.yaml
ENV HTTP_PORT=9090
ENV LOG_LEVEL=info
# 数据库配置(敏感信息应通过运行时注入)
# ENV DATABASE_URL=postgresql://...
```
### 非 root 用户运行
```dockerfile
# 创建非特权用户
RUN addgroup -g 1000 appuser && \
adduser -D -u 1000 -G appuser appuser
WORKDIR /app
# 复制二进制文件
COPY --from=builder /build/target/x86_64-unknown-linux-musl/release/your-binary-name .
# 修改所有权
RUN chown -R appuser:appuser /app
# 切换用户
USER appuser
CMD ["./your-binary-name"]
```
### 配置文件挂载
```dockerfile
# 在 Dockerfile 中创建配置目录
RUN mkdir -p /app/configs /app/logs
# 在 docker run 时挂载
# docker run -v ./configs:/app/configs -v ./logs:/app/logs your-image
```
## 构建命令示例
### 本地构建
```bash
# 基础构建
docker build -t your-service:latest .
# 指定 Dockerfile
docker build -f Dockerfile.ci -t your-service:latest .
# 传递构建参数
docker build --build-arg GIT_TAG=1.0.0 -t your-service:1.0.0 .
# 查看构建过程
docker build --progress=plain -t your-service:latest .
```
### 多平台构建
```bash
# 创建 buildx builder
docker buildx create --name mybuilder --use
# 构建并推送
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/your-service:latest \
--push \
.
```
### 优化构建速度
```bash
# 使用 BuildKit 缓存
export DOCKER_BUILDKIT=1
# 使用外部缓存
docker build \
--cache-from=type=registry,ref=your-service:buildcache \
--cache-to=type=registry,ref=your-service:buildcache,mode=max \
-t your-service:latest \
.
```
## 镜像大小优化
### 1. 使用 Alpine 基础镜像
```dockerfile
# Alpine 镜像体积小(~5MB
FROM alpine:3.21
```
### 2. 静态链接musl
```dockerfile
# 构建时使用 musl 目标,生成静态链接二进制
RUN cargo build --release --target x86_64-unknown-linux-musl
```
### 3. Strip 二进制文件
```toml
# Cargo.toml
[profile.release]
strip = true # 去除符号表
```
或在 Dockerfile 中:
```dockerfile
# 手动 strip
RUN strip target/x86_64-unknown-linux-musl/release/your-binary-name
```
### 4. 最小化层数
```dockerfile
# 合并多个 RUN 命令
RUN apk add --no-cache ca-certificates tzdata curl && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
addgroup -g 1000 appuser
```
### 5. 使用 .dockerignore
```
# .dockerignore
target/
.git/
.gitignore
*.md
tests/
benches/
```
## 安全建议
### 1. 使用特定版本标签
```dockerfile
# 不推荐:使用 latest
FROM alpine:latest
# 推荐:使用特定版本
FROM alpine:3.21
```
### 2. 定期更新依赖
```bash
# 更新 Cargo 依赖
cargo update
# 检查安全漏洞
cargo audit
```
### 3. 最小权限原则
```dockerfile
# 使用非 root 用户
USER appuser
# 只读文件系统(根据需要)
# docker run --read-only your-service
```
### 4. 不在镜像中包含敏感信息
```dockerfile
# 错误示例
# ENV DATABASE_PASSWORD=secret123
# 正确做法:通过运行时注入
# docker run -e DATABASE_PASSWORD=secret123 your-service
```
## 常见问题
### Q1: 镜像体积过大
**原因**
- 使用 `rust:latest` 作为运行镜像(>1GB
- 没有使用多阶段构建
- 包含 debug 符号
**解决方案**
```dockerfile
# 使用多阶段构建 + Alpine
FROM rust:1.83-alpine AS builder
# ... 构建步骤 ...
FROM alpine:3.21 # 最终镜像只有 ~20MB
COPY --from=builder /build/target/.../your-binary .
```
### Q2: openssl 链接错误
**错误信息**
```
error: linking with `cc` failed
ld: library not found for -lssl
```
**解决方案**
```dockerfile
# 方案 1安装 openssl-dev
RUN apk add --no-cache openssl-dev
# 方案 2使用 rustls 替代 openssl
# 在 Cargo.toml 中使用 rustls feature
```
### Q3: 交叉编译失败
**错误信息**
```
error: linker `aarch64-linux-musl-gcc` not found
```
**解决方案**
```bash
# 安装 musl 交叉编译工具链
rustup target add aarch64-unknown-linux-musl
# 或使用 cargo-zigbuild
cargo install cargo-zigbuild
cargo zigbuild --target aarch64-unknown-linux-musl
```
### Q4: 容器启动失败
**检查步骤**
```bash
# 查看日志
docker logs your-container
# 进入容器调试
docker run -it --entrypoint /bin/sh your-image
# 检查二进制是否可执行
docker run your-image ls -lh /app/
```
## 参考资源
- [Rust 官方 Docker 指南](https://docs.docker.com/language/rust/)
- [Alpine Linux 包搜索](https://pkgs.alpinelinux.org/packages)
- [Docker 多阶段构建文档](https://docs.docker.com/build/building/multi-stage/)
- [cargo-zigbuild](https://github.com/rust-cross/cargo-zigbuild)