【Rust 日报】2022-04-01 用于 Rust 应用程序的小而快的 Docker 映像

2022-04-18 15:37:24 浏览数 (1)

用于 Rust 应用程序的小而快的 Docker 映像

以下步骤将使用 Rocket “hello world” 应用程序作为演示。

Dockerfile 正常来说基本配置将是:

代码语言:javascript复制
# Dockerfile.plain

ARG BASE_IMAGE=rust:1.52.1-slim-buster

FROM $BASE_IMAGE
WORKDIR app
COPY . .
RUN cargo build --release
CMD ["./target/release/hello"]

然后构建镜像

代码语言:javascript复制
time docker build -f Dockerfile.plain -t hello:0.1.0 .

我们可以看到生成1.38GB 的镜像,构建时间为12 分钟。

代码语言:javascript复制
# build
real    12m13.412s
user    0m0.135s
sys     0m0.095s

REPOSITORY    TAG                  IMAGE ID       CREATED          SIZE
hello         0.1.0                ac4e1a72ba05   2 minutes ago    1.38GB
rust          1.52.1-slim-buster   61cb3c65a6ba   3 weeks ago      621MB

接下来使用多阶段构建和 cargo-chef 来使镜像尺寸更小

代码语言:javascript复制
# Dockerfile.chef

ARG BASE_IMAGE=rust:1.52.1-slim-buster

FROM $BASE_IMAGE as planner
WORKDIR app
RUN cargo install cargo-chef --version 0.1.20
COPY . .
RUN cargo chef prepare  --recipe-path recipe.json

FROM $BASE_IMAGE as cacher
WORKDIR app
RUN cargo install cargo-chef --version 0.1.20
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

FROM $BASE_IMAGE 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

FROM $BASE_IMAGE
COPY --from=builder /app/target/release/hello /
CMD ["./hello"]

它会生成628MB的图像大小,最后一次由于缓存的原因构建只需要1 分钟左右。

代码语言:javascript复制
# first test omitted
# second test
real    19m32.836s
user    0m0.188s
sys     0m0.088s

# third test
real    1m52.982s
user    0m0.060s
sys     0m0.088s

REPOSITORY   TAG    IMAGE ID       CREATED              SIZE
hello        0.1.0  ca1a9e1e5948   About a minute ago   628MB

更可以通过 distroless 或者 scratch 镜像来再加速构建,但是这里如果是 scratch 必须将工具链目标更改为 musl。

scratch:

代码语言:javascript复制
# Dockerfile.musl

ARG BASE_IMAGE=rust:1.52.1-slim-buster

FROM $BASE_IMAGE as planner
WORKDIR app
RUN cargo install cargo-chef --version 0.1.20
COPY . .
RUN cargo chef prepare  --recipe-path recipe.json

FROM $BASE_IMAGE as cacher
WORKDIR app
RUN cargo install cargo-chef --version 0.1.20
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

FROM $BASE_IMAGE as builder
WORKDIR app
COPY . .
# Copy over the cached dependencies
COPY --from=cacher /app/target target
COPY --from=cacher $CARGO_HOME $CARGO_HOME
# We need static linking for musl
RUN rustup target add x86_64-unknown-linux-musl
# `cargo build` doesn't work in static linking, need `cargo install`
RUN cargo install --target x86_64-unknown-linux-musl --path .

FROM scratch
COPY --from=builder /usr/local/cargo/bin/hello .
CMD ["./hello"]

结果:

代码语言:javascript复制
# first test ommitted
# second test
real    9m22.049s
user    0m0.113s
sys     0m0.103s

# third test
real    9m46.035s
user    0m0.120s
sys     0m0.085s

REPOSITORY   TAG    IMAGE ID       CREATED          SIZE
hello        0.1.0  332ce3b4f717   30 seconds ago   8.38MB

distroless:

代码语言:javascript复制
# Dockerfile.distroless

ARG BASE_IMAGE=rust:1.52.1-slim-buster

FROM $BASE_IMAGE as planner
WORKDIR app
RUN cargo install cargo-chef --version 0.1.20
COPY . .
RUN cargo chef prepare  --recipe-path recipe.json

FROM $BASE_IMAGE as cacher
WORKDIR app
RUN cargo install cargo-chef --version 0.1.20
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

FROM $BASE_IMAGE 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

FROM gcr.io/distroless/cc-debian10
COPY --from=builder /app/target/release/hello /
CMD ["./hello"]

结果:

代码语言:javascript复制
# first test ommitted
# second test
real    1m57.033s
user    0m0.045s
sys     0m0.038s

# third test
real    2m12.585s
user    0m0.093s
sys     0m0.096s

REPOSITORY   TAG    IMAGE ID       CREATED          SIZE
hello        0.1.0  118da37bdfe7   25 seconds ago   29MB

以上结果还是非常可观的。

结论 第一次尝试生成 1.38GB 的映像大小,构建时间为 12m。现在我们可以生成一个非常小的图像,并且构建速度非常快。选择权在你手中。如果您对 musl 目标没问题,请使用 scratch 镜像。否则,选择 distroless 。

  • https://azzamsa.com/n/rust-docker/
什么时候不使用 Rust?

Rust 在软件可靠性和性能方面向前迈出了一大步,这直接转化为节省的金钱和时间。Rust 解决了我作为开发人员每天面临的许多问题,例如不变性和良好的抽象。但与所有技术一样,Rust 也有一些缺点并使之不会成为您项目的最佳选择。今天 Sylvain Kerkour 想探讨一下他认为 Rust 的不好用例。

  • https://kerkour.com/why-not-rust

0 人点赞