强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Rust 系统编程语言完全教程 / 第24章:Docker 与部署

第24章:Docker 与部署

24.1 基本 Dockerfile

使用官方 Rust 镜像

# 基础镜像
FROM rust:1.79-bookworm as builder

WORKDIR /app

# 先复制依赖文件,利用 Docker 缓存
COPY Cargo.toml Cargo.lock ./
# 创建空 src/lib.rs 以缓存依赖
RUN mkdir src && echo "" > src/lib.rs && cargo build --release && rm -rf src

# 复制源码并构建
COPY src ./src
RUN cargo build --release

# 运行阶段
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/my-app /usr/local/bin/
EXPOSE 8080
CMD ["my-app"]

24.2 多阶段构建优化

分离依赖编译和源码编译

FROM rust:1.79-bookworm AS chef
RUN cargo install cargo-chef
WORKDIR /app

# 准备阶段:分析依赖
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

# 构建阶段:只编译依赖(利用缓存)
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

# 编译应用
COPY . .
RUN cargo build --release

# 运行阶段
FROM debian:bookworm-slim AS runtime
RUN apt-get update && \
    apt-get install -y --no-install-recommends ca-certificates && \
    rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/my-app /usr/local/bin/
EXPOSE 8080
ENTRYPOINT ["my-app"]

24.3 静态链接(musl)

使用 musl 实现完全静态链接

FROM rust:1.79-bookworm AS builder

# 安装 musl 工具链
RUN apt-get update && apt-get install -y musl-tools

# 添加 musl 目标
RUN rustup target add x86_64-unknown-linux-musl

WORKDIR /app
COPY . .

# 使用 musl 目标构建
RUN cargo build --release --target x86_64-unknown-linux-musl

# 运行阶段:使用 scratch(空镜像)
FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my-app /my-app
EXPOSE 8080
ENTRYPOINT ["/my-app"]

Cargo.toml 配置

# .cargo/config.toml
[target.x86_64-unknown-linux-musl]
rustflags = ["-C", "target-feature=+crt-static"]

# 使用 mold 链接器加速
[target.x86_64-unknown-linux-musl]
linker = "musl-gcc"

24.4 交叉编译

常见目标平台

目标说明
x86_64-unknown-linux-muslLinux x64 静态链接
aarch64-unknown-linux-muslLinux ARM64 静态链接
x86_64-unknown-linux-gnuLinux x64 动态链接
x86_64-pc-windows-gnuWindows x64
x86_64-apple-darwinmacOS x64
aarch64-apple-darwinmacOS ARM64 (M1/M2)
wasm32-unknown-unknownWebAssembly

使用 cross 工具

# 安装 cross
cargo install cross

# 交叉编译到 ARM64
cross build --release --target aarch64-unknown-linux-musl

# 交叉编译到 Windows
cross build --release --target x86_64-pc-windows-gnu

Docker 交叉编译(ARM64)

# 构建阶段
FROM --platform=linux/amd64 rust:1.79-bookworm AS builder

RUN apt-get update && apt-get install -y \
    gcc-aarch64-linux-gnu \
    musl-tools \
    && rm -rf /var/lib/apt/lists/*

RUN rustup target add aarch64-unknown-linux-musl

ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-gnu-gcc

WORKDIR /app
COPY . .
RUN cargo build --release --target aarch64-unknown-linux-musl

# 运行阶段(ARM64)
FROM --platform=linux/arm64 scratch
COPY --from=builder /app/target/aarch64-unknown-linux-musl/release/my-app /my-app
ENTRYPOINT ["/my-app"]

24.5 优化二进制大小

Cargo.toml 配置

[profile.release]
opt-level = "z"       # 优化大小
lto = true            # 链接时优化
codegen-units = 1     # 单编译单元
strip = true          # 去除符号
panic = "abort"       # panic 直接终止

进一步压缩

# 安装 UPX
sudo apt install upx-ucl

# 压缩二进制文件
upx --best target/release/my-app

# 对比大小
ls -lh target/release/my-app

使用 sstrip + UPX

FROM rust:1.79-bookworm AS builder

RUN apt-get update && apt-get install -y \
    musl-tools \
    upx-ucl \
    && rm -rf /var/lib/apt/lists/*

RUN rustup target add x86_64-unknown-linux-musl

WORKDIR /app
COPY . .
RUN cargo build --release --target x86_64-unknown-linux-musl

# 压缩二进制
RUN upx --best /app/target/x86_64-unknown-linux-musl/release/my-app

FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my-app /my-app
ENTRYPOINT ["/my-app"]

24.6 完整部署示例

Web 服务 Dockerfile

# ===== 构建阶段 =====
FROM rust:1.79-bookworm AS builder

RUN apt-get update && \
    apt-get install -y musl-tools pkg-config libssl-dev && \
    rm -rf /var/lib/apt/lists/*

RUN rustup target add x86_64-unknown-linux-musl

WORKDIR /app

# 缓存依赖
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs && \
    cargo build --release --target x86_64-unknown-linux-musl && \
    rm -rf src

# 编译应用
COPY . .
RUN touch src/main.rs  # 确保重新编译
RUN cargo build --release --target x86_64-unknown-linux-musl

# ===== 运行阶段 =====
FROM alpine:3.19 AS runtime

RUN addgroup -g 1000 app && \
    adduser -u 1000 -G app -s /bin/sh -D app

COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my-app /usr/local/bin/

# 复制配置文件
COPY config/ /etc/my-app/

USER app
EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1

CMD ["my-app", "--config", "/etc/my-app/config.toml"]

Docker Compose

version: '3.8'

services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
      - RUST_LOG=info
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mydb
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

24.7 CI/CD 集成

GitHub Actions

name: Build and Deploy

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Login to Registry
      uses: docker/login-action@v3
      with:
        registry: ghcr.io
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: ghcr.io/${{ github.repository }}:latest
        cache-from: type=gha
        cache-to: type=gha,mode=max

    - name: Cross-compile ARM64
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        platforms: linux/amd64,linux/arm64
        tags: ghcr.io/${{ github.repository }}:latest

24.8 本章小结

要点说明
多阶段构建分离构建和运行环境,减小镜像
musl静态链接,最小运行时依赖
交叉编译使用 cross 或 Docker 交叉编译
二进制优化LTO、strip、UPX 压缩
安全运行使用非 root 用户,scratch 镜像

扩展阅读

  1. Docker 官方文档 — Docker 使用指南
  2. cross 文档 — 交叉编译工具
  3. Rust 死二进制 — 二进制大小优化