有没有办法告诉Cargo安装和构建我的所有依赖项,但是没有尝试构建我的应用程序?
我认为cargo install
会这样做,但它实际上也会一直构建我的应用程序。我想进入一个状态,其中cargo build
会找到所有可以使用的依赖项,但不会触及/src
目录。
我真正想要实现的目标:
我正在尝试为Rust应用程序构建Docker镜像,我想在其中执行以下步骤:
构建时间(docker build .
):
运行时间(docker run ...
):
我已经尝试了以下Dockerfile
,但是指示的步骤也构建了我的应用程序(由于源目录尚未存在,当然会失败):
FROM jimmycuadra/rust
ADD Cargo.toml /source
ADD Cargo.lock /source
RUN cargo install # <-- failure here
ADD src /source/src
RUN cargo build
ENTRYPOINT cargo run
我想将安装依赖项步骤与实际构建我的应用程序分开的原因是,如果我不更改依赖项,我希望Docker能够使用已安装和构建所有依赖项的缓存映像。因此,在安装dependecies之后,我不能ADD /src /source/src
,因为当我更改自己的代码时,这会使缓存的图像无效。
答案 0 :(得分:6)
据我所知,在Cargo中只构建依赖项没有原生支持。有an open issue for it。如果你可以向Cargo提交一些东西来完成它,或者可能创建一个第三方Cargo插件,我不会感到惊讶。我也想要while True:
i = random.randint(0, 8)
j = random.randint(0, 9)
if i != j and X_valid[0][i] > 0 and X_valid[0][j] > 0:
break
X_valid[0][i] = 0
X_valid[0][j] = 0
的这个功能,当我自己的代码太破碎而无法编译时; - )
但是,我维护的Rust playground确实可以实现您的最终目标。有base Docker container安装Rustup并在Cargo.toml
中复制,并且所有的操作箱都可用于操场。 The build steps create a blank project (with a dummy src/lib.rs
), then calls cargo build
and cargo build --release
to compile the crates:
cargo doc
所有下载的包装箱都存储在Docker镜像的RUN cd / && \
cargo new playground
WORKDIR /playground
ADD Cargo.toml /playground/Cargo.toml
RUN cargo build
RUN cargo build --release
RUN rm src/*.rs
目录中,所有构建的包装箱都存储在应用程序$HOME/.cargo
目录中。
稍后,将真实的源文件复制到容器中,并使用现在编译的包装箱再次执行target/{debug,release}
/ cargo build
。
如果您正在构建可执行项目,那么您也希望复制Cargo.lock。
答案 1 :(得分:1)
如果添加虚拟主文件或lib文件,则可以使用cargo build
来下拉依赖项。我目前正在为基于Docker的项目使用此解决方案:
COPY Cargo.toml .
RUN mkdir src \
&& echo "// dummy file" > src/lib.rs \
&& cargo build
我正在使用--volumes
,所以我已经完成了这一点。主机卷进来并吹走虚拟文件,货物在我稍后构建源时使用缓存的依赖项。如果您想稍后添加COPY
(或ADD
)并使用缓存的依赖项,此解决方案也可以正常工作。
答案 2 :(得分:0)
FROM rust:1.37
WORKDIR /usr/src
# Create blank project
RUN USER=root cargo new PROJ
# We want dependencies cached, so copy those first.
COPY Cargo.toml /usr/src/PROJ/
COPY Cargo.lock /usr/src/PROJ/
WORKDIR /usr/src/PROJ
# This is a dummy build to get the dependencies cached.
RUN cargo build --release
# Now copy in the rest of the sources
COPY MyPROJECT/src /usr/src/PROJ/src/
# This is the actual build.
RUN cargo build --release \
&& mv target/release/appname /bin \
&& rm -rf /usr/src/PROJ
WORKDIR /
EXPOSE 8888
CMD ["/bin/appname"]
答案 3 :(得分:0)
我只想在此处发布此内容,以便其他人看到它的发展。我刚刚开始使用一个名为docker-wharf(https://github.com/denzp/cargo-wharf/tree/master/cargo-wharf-frontend)的Docker实验工具。这是一个Docker BuildKit前端,可为您缓存已构建的货物依存关系。如果仅更改一个源文件,则在调用docker build
时唯一要重建的内容。您可以通过注释Cargo.toml文件,然后将Docker定向到Cargo.toml而不是Dockerfile来使用它。去看看,这正是我想要的。 (我绝不隶属于该项目。)
答案 4 :(得分:0)
cargo-chef 工具旨在解决此问题。以下是 README 中关于如何在 Dockerfile 中使用它的示例:
FROM lukemathwalker/cargo-chef as planner
WORKDIR app
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM lukemathwalker/cargo-chef as cacher
WORKDIR app
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
FROM rust as builder
WORKDIR app
COPY . .
# Copy over the cached dependencies
COPY --from=cacher /app/target target
COPY --from=cacher $CARGO_HOME $CARGO_HOME
RUN cargo build --release --bin app
FROM rust as runtime
WORKDIR app
COPY --from=builder /app/target/release/app /usr/local/bin
ENTRYPOINT ["/usr/local/bin/app"]