Are*_* C. 25 rust docker dockerfile actix-web
我在 Rust + Actix-web 中有一个 hello world web 项目。我有几个问题。首先是代码的每次更改都会导致重新编译整个项目,包括下载和编译每个 crate。我想像在正常开发中一样工作 - 这意味着缓存编译的 crate 并且只重新编译我的代码库。第二个问题是它不会暴露我的应用程序。无法通过网络浏览器访问
Dockerfile:
FROM rust
WORKDIR /var/www/app
COPY . .
EXPOSE 8080
RUN cargo run
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
主.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()
}
Run Code Online (Sandbox Code Playgroud)
货物.toml:
[package]
name = "hello-world"
version = "0.1.0"
authors = []
edition = "2018"
[dependencies]
actix-web = "1.0"
Run Code Online (Sandbox Code Playgroud)
Cle*_*rer 27
似乎您并不是唯一一个通过 docker 构建过程缓存 Rust 依赖项的人。这是一篇很棒的文章,可以帮助您一路走来:https : //blog.mgattozzi.dev/caching-rust-docker-builds/
它的要点是您首先需要一个 dummy.rs 和您的 Cargo.toml,然后构建它以缓存依赖项,然后稍后复制您的应用程序源,以免每次构建都使缓存无效。
文件
FROM rust
WORKDIR /var/www/app
COPY dummy.rs .
COPY 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 . .
RUN cargo build --release
CMD ["target/release/app"]
Run Code Online (Sandbox Code Playgroud)
CMD 应用程序名称“app”基于您在 Cargo.toml 中为二进制文件指定的内容。
dummy.rs
fn main() {}
Run Code Online (Sandbox Code Playgroud)
Cargo.toml
[package]
name = "app"
version = "0.1.0"
authors = ["..."]
[[bin]]
name = "app"
path = "src/main.rs"
[dependencies]
actix-web = "1.0.0"
Run Code Online (Sandbox Code Playgroud)
src/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()
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*ten 10
使用(仍处于实验阶段)Docker Buildkit,您最终可以在一个docker build步骤中正确缓存构建文件夹:
Dockerfile:
# syntax=docker/dockerfile:experimental
from rust
ENV HOME=/home/root
WORKDIR $HOME/app
[...]
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/home/root/app/target \
cargo build --release
Run Code Online (Sandbox Code Playgroud)
然后运行:
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
小智 8
您可以使用cargo-chef多阶段构建来利用 Docker 层缓存。
FROM rust as planner
WORKDIR app
# We only pay the installation cost once,
# it will be cached from the second build onwards
RUN cargo install cargo-chef
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM rust as cacher
WORKDIR app
RUN cargo install cargo-chef
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
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"]
Run Code Online (Sandbox Code Playgroud)
它不需要 Buildkit,适用于简单的项目和工作区。您可以在发布公告中找到更多详细信息。
而electronicsix384128 的答案非常好。我想通过添加.cargo/git使用 git 的任何依赖项所需的缓存以及添加多级 docker 示例来扩展它。
使用 rust-musl-builder 和 Docker Buildkit 功能,该功能现在是 Docker Desktop 2.4 中的默认功能。在其他版本上,您可能仍然需要通过以下方式启用它:DOCKER_BUILDKIT=1 docker build .
rusl-musl-builder的工作目录/home/rust/src
尝试设置 uid/gid --mount,但由于目标中的权限问题而无法编译 Rust。
# syntax=docker/dockerfile:1.2
FROM ekidd/rust-musl-builder:stable AS builder
COPY . .
RUN --mount=type=cache,target=/home/rust/.cargo/git \
--mount=type=cache,target=/home/rust/.cargo/registry \
--mount=type=cache,sharing=private,target=/home/rust/src/target \
sudo chown -R rust: target /home/rust/.cargo && \
cargo build --release && \
# Copy executable out of the cache so it is available in the final image.
cp target/x86_64-unknown-linux-musl/release/my-executable ./my-executable
FROM alpine
COPY --from=builder /home/rust/src/my-executable .
USER 1000
CMD ["./my-executable"]
Run Code Online (Sandbox Code Playgroud)
这是对@ckaserer 的答案的改进,结合了评论和一些个人经验。它不需要您在存储库中创建虚拟文件,或在构建时编辑 Cargo.toml 文件。
RUN echo 'fn main() { panic!("Dummy Image Called!")}' > ./src/main.rs
COPY ["Cargo.toml", "Cargo.lock", "./"]
RUN cargo build --release
COPY src src
#need to break the cargo cache
RUN touch ./src/main.rs
RUN cargo build --release
Run Code Online (Sandbox Code Playgroud)
根据@ckaserer的答案,您可以RUN echo "fn main() {}" > ./src/main.rs在构建应用程序之前构建依赖项。
首先复制您的Cargo.toml和Cargo.lock文件并构建虚拟 main.rs 文件:
FROM rust as rust-builder
WORKDIR /usr/src/app
# Copy Cargo files
COPY ./Cargo.toml .
COPY ./Cargo.lock .
# Create fake main.rs file in src and build
RUN mkdir ./src && echo 'fn main() { println!("Dummy!"); }' > ./src/main.rs
RUN cargo build --release
Run Code Online (Sandbox Code Playgroud)
然后你可以复制真实的 src 目录并再次运行构建:
# Copy source files over
RUN rm -rf ./src
COPY ./src ./src
# The last modified attribute of main.rs needs to be updated manually,
# otherwise cargo won't rebuild it.
RUN touch -a -m ./src/main.rs
RUN cargo build --release
Run Code Online (Sandbox Code Playgroud)
然后我们可以将文件复制到 debain 的精简版本。这是完整的 docker 文件:
FROM rust as rust-builder
WORKDIR /usr/src/app
COPY ./Cargo.toml .
COPY ./Cargo.lock .
RUN mkdir ./src && echo 'fn main() { println!("Dummy!"); }' > ./src/main.rs
RUN cargo build --release
RUN rm -rf ./src
COPY ./src ./src
RUN touch -a -m ./src/main.rs
RUN cargo build --release
FROM debian:buster-slim
COPY --from=rust-builder /usr/src/app/target/release/app /usr/local/bin/
WORKDIR /usr/local/bin
CMD ["app"]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5834 次 |
| 最近记录: |