我一直在try 为我的rust build创建一个Dockerfile,它允许我独立于依赖项构建应用程序,如下所示:

然而,这似乎并不适用于我,因为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文件并执行了构建,与前面演示的类似.然而,由于我的项目 struct 略有不同,我似乎有一个问题,作为我的主要任务.rs几乎只有一行调用我库中的main方法.里布.rs也定义在我的toml文件中,该文件在构建依赖项之前被复制,并要求我touch 库.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示例项目,而不是在第二次构建之前复制的rocket应用程序.

据我所知,第一个构建似乎正在影响第二个构建,也许当我触及lib时.rs文件在虚拟shell项目中,它不使用run()方法构建它?所以当第二个启动时,它没有看到run方法,因为它是空的?但这对我来说没有多大意义,因为我已经复制了lib.包含run()方法的rs文件.

下面是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]
...

推荐答案

(一开始我无法复制这个.然后我注意到至少有一个依赖项似乎是一个必要条件.)

排队

RUN rm ./target/release/deps/rocket_example_pro*

你正在强制重建rocket_example_pro二进制文件.但该库将保持从第一个空文件构建的状态.试着换成

RUN rm ./target/release/deps/librocket_example_pro*

虽然就我个人而言,我认为从target目录中删除随机文件是一个非常有黑客性的解决方案.我更喜欢通过调整时间戳来触发库的重建:

RUN touch src/lib.rs && cargo build --release --locked ## Doesn't fail anymore

要想找到一个干净的解决方案,可以看看cargo chef.


[编辑:]这里发生了什么?

为了决定是否重建,cargo seems totarget/…/*.d的mtime与*.d文件内容中列出的文件的mtime进行比较.

可能先创建src/lib.rs个,然后运行docker build个.所以src/lib.rs年比target/release/librocket_example_pro.d年老,导致target/release/librocket_example_pro.rlib年在src/lib.rs年复制后没有重建.

你可以部分地验证这就是正在发生的事情.

  1. 使用原始Dockerfile,运行cargo build,看到它失败了吗
  2. 在docker外运行echo >> src/lib.rs以更新其mtime和哈希
  3. cargo build,它成功了

请注意,对于步骤2,用touch src/lib.rs更新mtime是不够的,因为docker在COPYing文件时将设置mtime,但在决定是否使用缓存的步骤时将设置ignore mtime.

Rust相关问答推荐

是否有一种可靠的方法可以将Arc弦乐转换/转换为Arc Vec u8>>

无需通过ASIO输入音频,并使用cpal进行反馈示例

PyReadonlyArray2到Vec T<>

交叉术语未正确清除屏幕

通过解引用将值移出Box(以及它被脱糖到什么地方)?

有没有办法避免在While循环中多次borrow `*分支`

除了调用`waker.wake()`之外,我如何才能确保future 将再次被轮询?

我们能确定Rust会优化掉Clone()吗?如果它会立即掉落?

rust中的库插件管理器,现在是否可行?

为什么我需要 to_string 函数的参考?

Windows 上 ndarray-linalg 与 mkl-stats 的链接时间错误

是否可以在不直接重复的情况下为许多特定类型实现一个函数?

存储返回 impl Trait 作为特征对象的函数

Rust 为什么被视为borrow ?

Rust 中 Mutex<> 的深拷贝?

有没有办法通过命令获取 Rust crate 的可安装版本列表?

在运行时在 Rust 中加载字体

如何将参数传递给Rust 的线程?

如何在 Rust 中编写涉及异步的重试函数

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?