Rust Docker编译配置方案

Rust Docker编译配置方案

AutumnSun

简单记录一下UXCI 这个Rust命令行工具的发布过程中遇到的问题以及解决方案.

问题: 运行环境中GLIBC缺失

问题的表现是: Linux下的编译结果无法在部分其他环境执行

报错内容为:

1
uxcirs: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by uxcirs)

这个错误是因为rust使用了动态链接, 因此依赖于系统的glibc库.

编译时使用的GLIBC_2.28(或者其他版本)在运行时的机器上不存在, 因此无法正常运行.

获取可用的 GLIBC 版本: ldd --version | head -1

各环境下的版本分别为: - 镜像ubuntu:18.04: ldd (Ubuntu GLIBC 2.27-3ubuntu1.6) 2.27 (sha256:8aa9c2798215f99544d1ce7439ea9c3a6dfd82de607da1cec3a8a2fae005931b) - VPS: ldd (Debian GLIBC 2.28-10+deb10u2) 2.28 - 镜像rust:latest: ldd (Debian GLIBC 2.31-13+deb11u5) 2.31 (sha256:557ff96cf0d2bed8fe24aded88a5dabbca8d71ff4fa66b696ed8a295247c92cc)

因此, VPS上编译得到的文件无法在 Ubuntu 18.04 中运行.

使用rust:latest镜像编译得到的文件无法在VPS和Ubuntu 18.04中运行.

让运行环境适配可执行文件也是一种选项, 但这个一般是对使用者来说的, 因此这次的需求中可以不用考虑.

而为了让二进制文件能适配更多的运行环境, 大致上有这几种思路: 1. 使用静态链接 2. 降低glibc版本

使用静态链接

StackOverflow中的

这里 还提到了静态编译glibc, 之后有需要的话可以尝试一下

降低glibc版本

由于Docker的存在, 这个选项实际执行起来还是比较方便的.

最终文件如下:

ci/cargo_config

1
2
3
4
5
[source.crates-io]
replace-with = 'mirror'

[source.mirror]
registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"

ci/dockerfile.builder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# syntax = docker/dockerfile:experimental
FROM ubuntu:18.04 AS linux-old-glibc

ENV LANG=C.UTF-8 XDG_CACHE_HOME=/var/cache PIP_CACHE_DIR=/var/cache/pip TZ=Asia/Shanghai DEBIAN_FRONTEND=noninteractive

# apt换源 & 避免apt缓存清理
RUN sed -i "s/\\w\+.ubuntu.com/mirrors.aliyun.com/g" /etc/apt/sources.list && \
cat /etc/apt/sources.list && \
mkdir -p $PIP_CACHE_DIR && rm -f /etc/apt/apt.conf.d/docker-clean

# 安装依赖
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update && \
apt-get install -y --no-install-recommends \
build-essential curl zip ca-certificates

# 安装rust
RUN curl https://sh.rustup.rs -sSfo rustup.sh && \
bash rustup.sh -y

# 更新PATH
ENV PATH="/root/.cargo/bin:$PATH"

# 配置cargo镜像
COPY ci/cargo_config ./
RUN cat cargo_config >> /root/.cargo/config

# 配置权限
RUN chmod 755 -R /root/.cargo
RUN mkdir -p /app/dist

# 配置工作目录
WORKDIR /app

FROM rust:latest AS linux

ENV LANG=C.UTF-8 XDG_CACHE_HOME=/var/cache PIP_CACHE_DIR=/var/cache/pip TZ=Asia/Shanghai DEBIAN_FRONTEND=noninteractive

# apt换源 & 避免apt缓存清理
RUN sed -i "s/\\w\+.debian.org/mirrors.aliyun.com/g" /etc/apt/sources.list && \
cat /etc/apt/sources.list && \
mkdir -p $PIP_CACHE_DIR && rm -f /etc/apt/apt.conf.d/docker-clean

# 配置cargo镜像
COPY ci/cargo_config $CARGO_HOME/config

WORKDIR /app
RUN mkdir -p /app/dist

FROM linux AS windows

# 安装依赖
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update && \
apt-get install -y --no-install-recommends \
g++-mingw-w64-x86-64 curl zip

RUN --mount=type=cache,target=/usr/local/cargo/registry \
rustup target add x86_64-pc-windows-gnu && \
rustup toolchain install stable-x86_64-pc-windows-gnu

WORKDIR /app
RUN mkdir -p /app/dist

然后分别使用 linux-old-glibc 和 windows 的镜像进行编译.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# syntax = docker/dockerfile:experimental
FROM rust-builder:linux-old-glibc AS linux-build

# 安装依赖
COPY Cargo.lock Cargo.toml ./
RUN --mount=type=cache,target=/usr/local/cargo/registry \
cargo fetch

# 执行编译
COPY src ./src
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/app/target \
cargo build --release && \
cp target/release/uxcirs dist/

FROM rust-builder:windows AS build

# 安装依赖
COPY Cargo.lock Cargo.toml ./
RUN --mount=type=cache,target=/usr/local/cargo/registry \
cargo fetch

# 复制代码
COPY src ./src
# 编译windows版本
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/app/target \
cargo build --release --target=x86_64-pc-windows-gnu && \
cp target/x86_64-pc-windows-gnu/release/*.exe dist/

几个可以注意一下的点: - Cargo.toml 中配置了[[bin]]之后, 可以直接使用cargo fetch. 或者, 可以写一个空的 src/main.rs - cargo build 指定了 --target 时, 生成的文件需要到 target/{target}/release/ 目录下去获取.

后续可以再参考rust官方镜像 , 优化一下构建镜像中的安装方式.

  • 标题: Rust Docker编译配置方案
  • 作者: AutumnSun
  • 创建于: 2023-04-06 12:08:48
  • 更新于: 2023-04-07 20:25:13
  • 链接: https://autumn21.top/blog/2023-04-06/b20b9c61f51b/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。