Docker 构建rust编译环境
为了解决rust交叉编译各种不兼容问题,使用docker直接构建运行时环境进行编译
=================================================================================
2025-12-31 更新
之前的方式每个项目都要创建镜像,直接更换思路,类似windows的wsl:
- 本地安装docker (本地mac, arm架构)
- 创建一个与运行环境一样的编译环境(要在x86_64架构的ubuntu服务器中运行,那就在docker构建这样的镜像)
构建ubuntu+rust的镜像,全换源。
Dockerfile
FROM ubuntu:24.04
LABEL org.opencontainers.image.source=https://github.com/rust-lang/docker-rust
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH \
RUST_VERSION=1.88.0
RUN set -eux; \
# apt换源
# 因为已经使用 -e(命令失败时立即退出)所以命令之间不用 && 符号连接
sed -i 's|http://.*archive.ubuntu.com|https://mirrors.ustc.edu.cn|g' /etc/apt/sources.list; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
gcc \
libc6-dev \
pkg-config \
libssl-dev \
wget \
; \
dpkgArch="$(dpkg --print-architecture)"; \
case "${dpkgArch##*-}" in \
amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='20a06e644b0d9bd2fbdbfd52d42540bdde820ea7df86e92e533c073da0cdd43c' ;; \
armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='3b8daab6cc3135f2cd4b12919559e6adaee73a2fbefb830fadf0405c20231d61' ;; \
arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='e3853c5a252fca15252d07cb23a1bdd9377a8c6f3efa01531109281ae47f841c' ;; \
i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='a5db2c4b29d23e9b318b955dd0337d6b52e93933608469085c924e0d05b1df1f' ;; \
*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
esac; \
# rustup换源
#url="https://static.rust-lang.org/rustup/archive/1.28.2/${rustArch}/rustup-init"; \
url="https://mirrors.ustc.edu.cn/rust-static/rustup/archive/1.28.2/${rustArch}/rustup-init"; \
wget "$url"; \
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
chmod +x rustup-init; \
export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static; \
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
rm rustup-init; \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
rustup --version; \
cargo --version; \
rustc --version; \
apt-get remove -y --auto-remove \
wget \
; \
rm -rf /var/lib/apt/lists/*; \
# cargo 换源
echo '[source.crates-io]\n\
replace-with = "ustc"\n\
[source.ustc]\n\
registry = "https://mirrors.ustc.edu.cn/crates.io-index"' > $CARGO_HOME/config.toml;
执行脚本,mac用户这里要注意选择对应平台
#!/bin/bash
BUILDER="rust_builder"
docker build --platform=linux/amd64 -t $BUILDER .
镜像构建完成
到此为止已经完成了99%,后面就是运行容器编译产物,有几个细节需要注意:
#!/bin/bash
BUILDER="rust_builder"
CARGO_HOME="/usr/local/cargo"
ROOT="/Users/xxx/rust-demo"
docker run --rm \
-v "$ROOT":/workspace \
-v rust_builder_cargo_registry:"$CARGO_HOME"/registry \
-v rust_builder_cargo_git:"$CARGO_HOME"/git \
-w /workspace \
-e CARGO_TARGET_DIR=/workspace/target-linux \
$BUILDER \
cargo build --release
- 对应的镜像名,cargo目录要写正确,与构建镜像的一致。
- 将项目
rust-demo目录挂载到容器内的 /workspace - 使用了持久化缓存卷
rust_builder_cargo_registry,rust_builder_cargo_git提升后续编译速度 - 因为直接使用了磁盘挂载到容器的方式,所以为了与宿主机隔离
target目录,主动更改了编译产物位置为target-linux
=================================================================================
以下是之前旧的方式
Dockerfile
FROM ubuntu:24.04
LABEL org.opencontainers.image.source=https://github.com/rust-lang/docker-rust
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH \
RUST_VERSION=1.88.0
RUN set -eux; \
# apt换源
# 因为已经使用 -e(命令失败时立即退出)所以命令之间不用 && 符号连接
sed -i 's|http://.*archive.ubuntu.com|https://mirrors.ustc.edu.cn|g' /etc/apt/sources.list; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
gcc \
libc6-dev \
pkg-config \
libssl-dev \
wget \
; \
dpkgArch="$(dpkg --print-architecture)"; \
case "${dpkgArch##*-}" in \
amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='20a06e644b0d9bd2fbdbfd52d42540bdde820ea7df86e92e533c073da0cdd43c' ;; \
armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='3b8daab6cc3135f2cd4b12919559e6adaee73a2fbefb830fadf0405c20231d61' ;; \
arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='e3853c5a252fca15252d07cb23a1bdd9377a8c6f3efa01531109281ae47f841c' ;; \
i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='a5db2c4b29d23e9b318b955dd0337d6b52e93933608469085c924e0d05b1df1f' ;; \
*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
esac; \
# rustup换源
#url="https://static.rust-lang.org/rustup/archive/1.28.2/${rustArch}/rustup-init"; \
url="https://mirrors.ustc.edu.cn/rust-static/rustup/archive/1.28.2/${rustArch}/rustup-init"; \
wget "$url"; \
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
chmod +x rustup-init; \
export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static; \
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
rm rustup-init; \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
rustup --version; \
cargo --version; \
rustc --version; \
apt-get remove -y --auto-remove \
wget \
; \
rm -rf /var/lib/apt/lists/*; \
# cargo 换源
echo '[source.crates-io]\n\
replace-with = "ustc"\n\
[source.ustc]\n\
registry = "https://mirrors.ustc.edu.cn/crates.io-index"' > $CARGO_HOME/config.toml;
WORKDIR /app
# 利用 Docker 层缓存优化:先复制配置文件和依赖声明
# 这样只有在 Cargo.toml/Cargo.lock 改变时才会重新编译依赖
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs \
&& cargo build --release \
&& rm -f target/release/usdt-bridge*
# 现在复制实际源代码并构建
COPY src ./src
# 强制更新源码文件时间戳,确保 Cargo 知道需要重新编译应用代码
RUN touch src/main.rs && cargo build --release
# 层缓存另一种判断写法
COPY Cargo.toml Cargo.lock ./
RUN mkdir -p src
RUN [ ! -f src/main.rs ] && echo "fn main() {}" > src/main.rs || true
RUN cargo build --release && rm -f target/release/usdt-bridge*
COPY src ./src
RUN touch src/main.rs && cargo build --release
shell
#!/bin/bash
BUILDER="usdt-bridge-builder"
TARGET="/app/target/release/usdt-bridge"
docker build -t $BUILDER .
CONTAINER=$(docker create $BUILDER)
docker cp $CONTAINER:/app/target/release/usdt-bridge ~
docker rm $CONTAINER
echo "file copied to $HOME/usdt-bridge"
- 主要都来自
https://github.com/rust-lang/docker-rustrust官方镜像的构建方式 - 替换了运行时环境依赖 (debian:bullseye-slim -> ubuntu:24.04)
- 对apt-get rustup cargo 进行了换源

浙公网安备 33010602011771号