如何在 docker 中緩存加速 Rust 依賴構建

文章目錄

最近開始學習 《陳天 · Rust 編程第一課》,在用docker鏡像打包構建代碼示例時,每次都會在更新crate.io索引上等上一會,即便在沒有修改Cargo.tomal依賴的前提下。

想着難道沒有辦法緩存下更新麼,於是就有了這篇新手踩坑指南。

本地緩存 - 失敗

查閱有在docker中指定CARGO_HOME到宿主機來緩存crate.io索引

命令如下:

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 失敗了

   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 二進制失敗原因分析 [1] 和 Unable to run a Docker image with a Rust executable[2]

鏡像緩存 - 成功

然後就搜到了這篇 cache-rust-dependencies-with-docker-build[3]

真是非常 tricky!

思想很簡單,就是緩存要在依賴不變的前提下,而 docker build 時源代碼更改會使緩存的docker layer失效。

那就先用一個不會變的源代碼編譯依賴,編譯好了依賴緩存 layer,再文件替換到實際代碼,重新進行編譯就正常運行加緩存兩不誤了。

具體構建方式如下:

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指定打包的程序名和路徑

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

打包和運行則可以一行命令搞定:

# 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")" #"$@"

運行時:

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

完美緩存了依賴更新,可以繼續學習了

本文代碼示例詳見 rust-koan[4]

參考資料

[1]

Rust 交叉編譯 OSX 二進制失敗原因分析: https://ttys3.dev/post/rust-cross-compile-darwin-target-troubleshooting/

[2]

Unable to run a Docker image with a Rust executable: https://stackoverflow.com/a/49173699/4431337

[3]

cache-rust-dependencies-with-docker-build: https://stackoverflow.com/a/58474618/4431337

[4]

rust-koan: https://github.com/NewbMiao/rust-koan

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Sh2-92U4fKS4PUMFCZyMug