Closed1

axumで数MBのstatic distrolessサーバー

黒ヰ樹黒ヰ樹

2024/01/21追記:新しく記事を書きました。この記事で書いたソースコードは間違ってはいないのですが新しい記事で紹介したソースコードで書くことをオススメします。

https://zenn.dev/tkithrta/articles/cb91f6c8246d9a


Rustなにもわからないし情報の裏取りが面倒なのでスクラップに投げておきます。多分本番環境で動かして問題ないやつだけど何らの責任も負わないものとします。

https://github.com/clux/muslrust

FROM ekidd/rust-musl-builder:stable AS builderからFROM scratchでイメージ作るよりFROM clux/muslrust:stable AS builderからFROM gcr.io/distroless/staticでイメージ作ったほうが早いし安定している。
みんなもやってみよう。
Dockerだけあれば動きます。

$ mkdir -p axum-hello-world axum-hello-world/src
$ cd axum-hello-world
$ touch Dockerfile Cargo.toml src/main.rs
Dockerfile
FROM clux/muslrust:stable AS builder

WORKDIR /volume
COPY . .

RUN RUSTFLAGS="-C strip=symbols" cargo build --release

FROM gcr.io/distroless/static

WORKDIR /
COPY --from=builder /volume/target/x86_64-unknown-linux-musl/release/axum-hello-world .

CMD ["/axum-hello-world"]
Cargo.toml
[package]
name = "axum-hello-world"
version = "0.1.0"
edition = "2021"

[dependencies]
axum = "*"
axum-server = "*"
tokio = { version = "*", features = ["full"] }
main.rs
use axum::{routing::get, Router};
use axum_server::Handle;
use std::{net::SocketAddr, time::Duration};
use tokio::time::sleep;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(|| async { "Hello, World!" }));
    let handle = Handle::new();
    tokio::spawn(shutdown(handle.clone()));
    let addr = SocketAddr::from(([0, 0, 0, 0], 8080));
    println!("listening on {}", addr);
    axum_server::bind(addr)
        .handle(handle)
        .serve(app.into_make_service())
        .await
        .unwrap();
    println!("server is shut down");
}

async fn shutdown(handle: Handle) {
    sleep(Duration::from_secs(10)).await;
    println!("sending shutdown signal");
    handle.shutdown();
}

以上事前準備。
10秒ぐらいでシャットダウンするエフェメラルなサーバーは下記コマンドで立ち上げる。

$ docker build -t axum-hello-world .
$ docker run -d --rm -p 8080:8080 axum-hello-world
...

Dockerで動いているstaticバイナリをローカルにコピーして実行するコマンド。

$ docker build -t axum-hello-world .
$ docker run -d --rm -p 8080:8080 axum-hello-world
$ docker cp "$(docker ps -aq | head -n1):/axum-hello-world" axum-hello-world
$ ./axum-hello-world
listening on 0.0.0.0:8080
sending shutdown signal
server is shut down

バイナリサイズは2.7MB、イメージサイズは5.25MB。

$ ls -lahR
./axum-hello-world:
total 2.7M
drwxr-xr-x 3 gitpod gitpod   77 Aug 27 07:00 .
drwxr-xr-x 3 gitpod gitpod   31 Aug 27 07:00 ..
-rwxr-xr-x 1 gitpod gitpod 2.7M Aug 27 07:00 axum-hello-world
-rw-r--r-- 1 gitpod gitpod  163 Aug 27 07:00 Cargo.toml
-rw-r--r-- 1 gitpod gitpod  276 Aug 27 07:00 Dockerfile
drwxr-xr-x 2 gitpod gitpod   21 Aug 27 07:00 src

./axum-hello-world/src:
total 4.0K
drwxr-xr-x 2 gitpod gitpod  21 Aug 27 07:00 .
drwxr-xr-x 3 gitpod gitpod  77 Aug 27 07:00 ..
-rw-r--r-- 1 gitpod gitpod 716 Aug 27 07:00 main.rs

$ docker images
REPOSITORY         TAG       IMAGE ID       CREATED              SIZE
axum-hello-world   latest    ...            About a minute ago   5.25MB

10秒ぐらいでシャットダウンする機能はaxumを少し便利にしたaxum-serverのExampleを参考にした。

https://github.com/programatik29/axum-server/blob/master/examples/shutdown.rs

https://github.com/programatik29/axum-server

https://programatik29.github.io/axum-tutorial/

Eray-sanのAxum Tutorialはシンプルでわかりやすいのでオススメ。

このスクラップは2024/01/21にクローズされました