我在Rust + Actix-web中有Hello World Web项目。我有几个问题。首先是代码的每一次更改都会导致重新编译整个项目,包括下载和编译每个板条箱。我想像正常开发一样工作-这意味着缓存编译的板条箱,只重新编译我的代码库。第二个问题是它不会暴露我的应用程序。它无法通过Web浏览器访问
停靠文件:
FROM rust
WORKDIR /var/www/app
COPY . .
EXPOSE 8080
RUN cargo run
docker-compose.yml:
version: "3"
services:
app:
container_name: hello-world
build: .
ports:
- '8080:8080'
volumes:
- .:/var/www/app
- registry:/root/.cargo/registry
volumes:
registry:
driver: local
main.rs:
extern crate actix_web;
use actix_web::{web, App, HttpServer, Responder};
fn index() -> impl Responder {
"Hello world"
}
fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(web::resource("/").to(index)))
.bind("0.0.0.0:8080")?
.run()
}
Cargo.toml:
[package]
name = "hello-world"
version = "0.1.0"
authors = []
edition = "2018"
[dependencies]
actix-web = "1.0"
9条答案
按热度按时间wkftcu5l1#
看起来您并不是唯一一个通过Docker构建过程来缓存rust依赖项的奋进。下面是一篇很棒的文章,可以帮助您:https://blog.mgattozzi.dev/caching-rust-docker-builds/
其要点是,首先需要一个dummy.rs和Cargo.toml,然后构建它来缓存依赖项,然后在以后复制应用程序源代码,以便不会在每次构建时该高速缓存无效。
停靠文件
CMD应用程序名称“app”基于您在Cargo.toml中为二进制文件指定的内容。
虚拟.rs
载货汽车
源代码/main.rs
9cbw7uwe2#
使用Docker Buildkit(仍处于实验阶段),您最终可以在
docker build
步骤中正确地缓存构建文件夹:停靠文件:
然后运行:
DOCKER_BUILDKIT=1 docker build . --progress=plain
个后续的Docker构建将重用缓存中的货物和目标文件夹,从而大大加快构建速度。
要清除Docker缓存装载,请执行以下操作:
docker builder prune --filter type=exec.cachemount
如果您没有看到正确的缓存:如果您没有看到正确的缓存,请确保确认您的货物/注册表和目标文件夹在Docker映像中的位置。
最小工作示例:https://github.com/benmarten/sccache-docker-test/tree/no-sccache
ru9i0ody3#
您可以使用
cargo-chef
通过多阶段构建来利用Docker图层缓存。它不需要Buildkit,可以用于简单的项目和工作区。您可以在release announcement中找到更多的细节。
q5lcpyga4#
根据@ckaserer的回答,您可以在构建应用程序之前使用
RUN echo "fn main() {}" > ./src/main.rs
构建依赖项。首先,只复制
Cargo.toml
和Cargo.lock
文件,并构建虚拟的main.rs文件:然后,您可以复制真实的的src目录并再次运行build:
然后,我们可以将文件复制到一个精简版的debain中。
qybjjes15#
虽然electronix384128的答案很好,但我想通过为
.cargo/git
添加缓存来扩展它,这是使用git的任何依赖项所需要的,并添加一个多级Docker示例。使用rust-musl-builder和Docker Buildkit功能,这是Docker Desktop 2.4中的默认功能。在其他版本中,您可能仍需要通过以下方式启用该功能:
DOCKER_BUILDKIT=1 docker build .
个rusl-musl-builder
的工作目录是/home/rust/src
已尝试在
--mount
上设置uid/gid,但由于目标中的权限问题而无法编译rust。ffscu2ro6#
我认为问题是你的
volumes
定义没有进行绑定挂载。我相信你当前的配置是将HOST ./registry/
复制到DOCKER /root/.cargo/registry/
,写入DOCKER /root/.cargo/registry/
,并在容器关闭时丢弃内容。相反,您需要在卷上指定
bind
类型:但是,请记住,也会创建一个
/root/.cargo/.package-cache
文件,但不会保存在这里。相反,您可以将source
更改为./.cargo
,并将目标更改为/root/.cargo
。为了我自己(大多数是cli)rust项目,我喜欢使用一个drop-in replacement I've written for
cargo
,我已经确认它在构建之间缓存了包,大大减少了构建时间。它可以被复制到/usr/local/bin
以供全局使用,或者在单个项目中作为./cargo build
运行。但是请记住,这个特定的脚本假设应用程序位于容器中的/usr/src/app
,所以可能需要根据您的使用情况进行调整。kulphzqa7#
这就是我所做的,它与构建脚本兼容。这是一个多阶段的构建,所以它会产生一个小的映像,但是会在第一个映像中缓存构建的依赖项。
ktca8awb8#
我遇到了与您完全相同的问题,并尝试了多种方法通过缓存依赖项来缩短构建时间。
1. @卡塞勒的回答
它完成了工作,并且简单易懂地解释了它为什么工作,这是一个很好的解决方案。然而,这归结为偏好,但是如果你不以这种方式缓存依赖项,你可以遵循#2。
2.使用
cargo-chef
@LukeMathWalker,创建者自己,完成了使用
cargo-chef
的必要步骤,但这里有一个来自github页面的 * 稍微调整的例子。停靠文件
您应该注意到,通过上述更改,构建时间显著缩短!
边注,据我所知,this blog entry,虽然不是在dockerized构建,拥有最好的信息编译rust应用程序更快地在您的本地机器上。你可能会发现它很有帮助,所以我建议你看看它,如果你有兴趣。
kuarbcqp9#
这是对@ckaserer的回答的改进,其中包含了注解和一些个人经验。它不需要您在repo中创建一个虚拟文件,或者在构建时编辑Cargo.toml文件。