3

如何为Rust创建小型Docker镜像? - DEV

 1 year ago
source link: https://www.jdon.com/62766
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何为Rust创建小型Docker镜像? - DEV


构建最小的 Docker 镜像来部署 Rust 带来了很多好处:它不仅有利于安全性(减少攻击面),而且可以缩短部署时间、降低成本(减少带宽和存储),并降低依赖冲突的风险。

我们的 "应用程序 "相当简单:我们将建立一个命令行工具,调用https://api.myip.com,并打印出结果。

进行HTTPS调用很有意思,因为它需要一个与TLS交互的库,通常是openssl。但为了建立尽可能小的Docker镜像,我们需要静态链接我们的程序,而静态链接openssl并不那么容易。这就是为什么我们要避免使用openssl,而使用rustls。

$ cargo new myip

Cargo.toml:

[package]
name = "myip"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

<p class="indent">[dependencies]
serde = { version = "1", features = ["derive"] }
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls", "blocking"] }


<p class="indent">[target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies.jemallocator]
version = "0.3"

main.rs:

use serde::Deserialize;
use std::error::Error;

// Use Jemalloc only for musl-64 bits platforms
#[cfg(all(target_env = "musl", target_pointer_width = "64"))]
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

#[derive(Deserialize, Debug)]
struct ApiRes {
    ip: String,
}

fn main() -> Result<(), Box<dyn Error>> {
    let res = reqwest::blocking::get("https://api.myip.com")?.json::<ApiRes>()?;

    println!("{}", res.ip);

    Ok(())
}
$ cargo run
     Running `target/debug/myip`
127.0.0.1

FROM scratch
Size: 15.9 MB

为了使用FROM scratch作为基础镜像,我们必须将我们的程序静态链接到musl libc,因为glibc在scratch中是不可用的。这可以通过使用x86_64-unknown-linux-musl目标来实现。

这种方法的一个问题是,musl的内存分配器没有进行速度优化,可能会降低你的应用程序的性能,特别是在处理高吞吐量的应用程序时。

这就是为什么我们使用 jemalloc,一个为高并发应用设计的内存分配器。

Dockerfile.scratch

####################################################################################################
## Builder
####################################################################################################
FROM rust:latest AS builder

RUN rustup target add x86_64-unknown-linux-musl
RUN apt update && apt install -y musl-tools musl-dev
RUN update-ca-certificates

# Create appuser
ENV USER=myip
ENV UID=10001

RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    "${USER}"


WORKDIR /myip

COPY ./ .

RUN cargo build --target x86_64-unknown-linux-musl --release

####################################################################################################
## Final image
####################################################################################################
FROM scratch

# Import from builder.
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group

WORKDIR /myip

# Copy our build
COPY --from=builder /myip/target/x86_64-unknown-linux-musl/release/myip ./

# Use an unprivileged user.
USER myip:myip

CMD ["/myip/myip"]

运行:

$ docker build -t myip:scratch -f Dockerfile.scratch .
# ...
$ docker run -ti --rm myip:scratch
127.0.0.1

FROM alpine
Size: 21.6MB


Alpine Linux是一个以安全为导向,基于musl libc和busybox的轻量级Linux发行版。

当FROM scratch不够用,而你需要一个软件包管理器来安装chromium或ssh等依赖项时,就应该使用它。

由于它是基于musl libc的,因此具有与FROM scratch相同的限制,我们需要使用x86_64-unknown-linux-musl静态链接我们的Rust程序。
Dockerfile.alpine:

####################################################################################################
## Builder
####################################################################################################
FROM rust:latest AS builder

RUN rustup target add x86_64-unknown-linux-musl
RUN apt update && apt install -y musl-tools musl-dev
RUN update-ca-certificates

# Create appuser
ENV USER=myip
ENV UID=10001

RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    "${USER}"


WORKDIR /myip

COPY ./ .

RUN cargo build --target x86_64-unknown-linux-musl --release

####################################################################################################
## Final image
####################################################################################################
FROM alpine

# Import from builder.
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group

WORKDIR /myip

# Copy our build
COPY --from=builder /myip/target/x86_64-unknown-linux-musl/release/myip ./

# Use an unprivileged user.
USER myip:myip

CMD ["/myip/myip"]

运行:

$ docker build -t myip:alpine -f Dockerfile.alpine .
# ...
$ docker run -ti --rm myip:alpine
127.0.0.1

更多:你可以在 GitHub 上找到代码:github.com/skerkour/kerkour.com
 


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK