Files
voson 425ca5b5fd feat(gitea): 添加 Dockerfile 模板和 Rust 支持,优化 runner 网络配置说明
- 新增 Go、Node.js、Rust 服务的 Dockerfile 模板
- 新增 Rust 快速参考指南
- 新增 Rust 后端工作流模板
- 优化 create-runner.md,明确 host 网络模式为缓存必需条件
- 更新 gitea skill 主文档
2026-01-30 10:12:09 +08:00

572 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)