我一直在嘗試為我的 rust 構建創建一個 Dockerfile,它允許我將應用程式與依賴項分開構建,如下所示: Cache Rust dependencies with Docker build
但是,這似乎對我不起作用,與 lib.rs 檔案的作業樹略有不同。我的 Dockerfile 布局如下:
FROM rust:1.60 as build
# create a new empty shell project
RUN USER=root cargo new --bin rocket-example-pro
WORKDIR /rocket-example-pro
# create dummy lib.rs file to build dependencies separately from changes to src
RUN touch src/lib.rs
# copy over your manifests
COPY ./Cargo.lock ./Cargo.lock
COPY ./Cargo.toml ./Cargo.toml
RUN cargo build --release --locked
RUN rm src/*.rs
# copy your source tree
COPY ./src ./src
# build for release
RUN rm ./target/release/deps/rocket_example_pro*
RUN cargo build --release --locked ## <-- fails
# our final base
FROM rust:1.60
# copy the build artifact from the build stage
COPY --from=build /rocket-example-pro/target/release/rocket_example_pro .
# set the startup command to run your binary
CMD ["./rocket_example_pro"]
正如您最初看到的那樣,我復制了 toml 檔案并執行構建,與之前演示的類似。但是,由于我的專案結構略有不同,我似乎遇到了問題,因為我的 main.rs 幾乎只有一行呼叫我的 lib.rs 中的 main 方法。lib.rs 也在我的 toml 檔案中定義,該檔案在構建依賴項之前被復制,并要求我觸摸 lib.rs 檔案以使其不會在此處構建失敗,否則會丟失。
在我似乎無法解決的第二個構建步驟中,在我復制了實際的源檔案以構建應用程式之后,我收到了錯誤訊息
Compiling rocket_example_pro v0.1.0 (/rocket-example-pro)
error[E0425]: cannot find function `run` in crate `rocket_example_pro`
--> src/main.rs:3:22
|
3 | rocket_example_pro::run().unwrap();
| ^^^ not found in `rocket_example_pro`
當我自己在一個空目錄中執行這些步驟時,我自己似乎沒有遇到同樣的錯誤,而是最后一步成功了,但是生成的 Rocket-example-pro 可執行檔案似乎仍然是僅列印“Hello world”的 shell 示例專案' 而不是我在第二次構建之前復制的火箭應用程式。
據我所知,第一個構建似乎影響了第二個,也許當我觸摸虛擬 shell 專案中的 lib.rs 檔案時,它在沒有 run() 方法的情況下構建它?所以當第二個啟動時,它看不到 run 方法,因為它是空的?但這對我來說沒有多大意義,因為我已經復制了 lib.rs 檔案,其中包含 run() 方法。
如果有幫助,這就是 toml 檔案的樣子:
[package]
name = "rocket_example_pro"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "rocket_example_pro"
path = "src/main.rs"
[lib]
name = "rocket_example_pro"
path = "src/lib.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
...
uj5u.com熱心網友回復:
(起初我無法重現這一點。然后我注意到至少有一個依賴項似乎是必要條件。)
隨著線
RUN rm ./target/release/deps/rocket_example_pro*
您正在強制重建rocket_example_pro二進制檔案。但是該庫將保持從第一個空檔案構建的狀態。嘗試更改為
RUN rm ./target/release/deps/librocket_example_pro*
雖然就個人而言,我認為從目錄中洗掉隨機檔案target是一個非常糟糕的解決方案。我更愿意通過調整時間戳來觸發 lib 的重建:
RUN touch src/lib.rs && cargo build --release --locked ## Doesn't fail anymore
要獲得干凈的解決方案,請查看 cargo-chef。
[編輯:] 那么這里發生了什么?
為了決定是否重建,cargo似乎target/…/*.d將檔案的 mtime 與檔案內容中列出的檔案的 mtime進行比較*.d。
可能src/lib.rs是先創建,然后docker build運行。sosrc/lib.rs比舊target/release/librocket_example_pro.d,導致target/release/librocket_example_pro.rlib復制進去后不重建src/lib.rs。
您可以部分驗證正在發生的事情。
- 使用原始的 Dockerfile,運行
cargo build,看到它失敗 - 在 docker 外部運行
echo >> src/lib.rs以更新其 mtime 和 hash - 運行
cargo build,成功
請注意,對于步驟 2,更新 mtimetouch src/lib.rs是不夠的,因為 docker 會設定mtimewhenCOPY檔案,但在決定是否使用快取步驟時會忽略 mtime 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/473648.html
標籤:码头工人 锈 dockerfile 锈货
