如何在docker中缓存加速Rust依赖构建

文章目录

  1. 1. 本地缓存 - 失败
  2. 2. 镜像缓存 - 成功

最近开始学习《陈天 · Rust 编程第一课》,在用docker镜像打包构建代码示例时,每次都会在更新crate.io索引上等上一会,即便在没有修改Cargo.tomal依赖的前提下。

想着难道没有办法缓存下更新么,于是就有了这篇新手踩坑指南。

本地缓存 - 失败

查阅有在docker中指定CARGO_HOME到宿主机来缓存crate.io索引

命令如下:

1
docker run --rm --user "$(id -u)":"$(id -g)" -v "$PWD":/usr/src/myapp -w /usr/src/myapp -e CARGO_HOME=".cargo" rust cargo run

结果,镜像run失败了

1
2
3
4
5
6
7
8
9
10
11
12
   Compiling libc v0.2.107
Compiling autocfg v1.0.1
Compiling siphasher v0.3.7
Compiling unicode-xid v0.2.2
Compiling memchr v2.4.1
Compiling lazy_static v1.4.0
Compiling ppv-lite86 v0.2.15
Compiling pin-project-lite v0.2.7
Compiling pkg-config v0.3.22
error: failed to build archive: Input/output error

error: error writing dependencies to `/usr/src/myapp/.target/debug/deps/pkg_config-8dafe7024c916ac6.d`: Input/output error (os error 5)

一番查阅,应该是环境不一致时pkg-config编译时链接库有问题,详见 Rust 交叉编译 OSX 二进制失败原因分析Unable to run a Docker image with a Rust executable

镜像缓存 - 成功

然后就搜到了这篇cache-rust-dependencies-with-docker-build

真是非常tricky!

思想很简单,就是缓存要在依赖不变的前提下,而docker build时源代码更改会使缓存的docker layer失效。

那就先用一个不会变得源代码编译依赖,编译好依赖缓存layer,再文件替换到实际代码,重新进行编译就正常运行加缓存两不误了。

具体构建方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
FROM rust
WORKDIR /app
RUN echo "fn main() {}" > dummy.rs
ARG SRC_DIR
ENV SRC_DIR=${SRC_DIR:-}
COPY ${SRC_DIR}/Cargo.toml .
RUN sed -i 's#src/main.rs#dummy.rs#' Cargo.toml
RUN cargo build --release
RUN sed -i 's#dummy.rs#src/main.rs#' Cargo.toml
COPY ${SRC_DIR}/. .
RUN cargo build --release
ENTRYPOINT ["target/release/app"]

这里构建参数SRC_DIR是为了指定不同代码,复用同一个Dockerfile

相应的Cargo.toml指定打包的程序名和路径

1
2
3
[[bin]]
name = "app"
path = "src/main.rs"

打包和运行则可以一行命令搞定:

1
2
3
4
5
# run.sh
#!/usr/bin/env bash

WORKSPACE=$(cd "$(dirname "$0")" && pwd -P)
docker run --rm -it "$(docker build --build-arg SRC_DIR="$SRC_DIR" -q "$WORKSPACE" -t "rust-$SRC_DIR")" #"$@"

运行时:

1
2
# eg:
# SRC_DIR=scrape_url sh run.sh https://www.rust-lang.org/ rust.md

完美缓存了依赖更新,可以继续学习了

另外也推荐下陈天老师的rust课,由浅入深,感兴趣的同学可以试试

陈天 · Rust 编程第一课

本文代码示例详见rust-koan

如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com 本文链接 : http://blog.newbmiao.com/2021/11/21/cache-rust-dependencies-with-docker-build.html