💪

Wadoランタイムをマッスルにしたい

に公開

マッスル

ここでいうマッスルとは筋肉のことではなく、musl libcのことです。

https://musl.libc.org/

Wadoを使っていると、毎回Rustの開発環境を用意してcargo installするのではなく、様々な環境で使えるビルドされた小さなランタイムとして持っておきたくなります。

https://github.com/wado-lang/wado

そこで以前使ったことのあるmuslrustでビルドしてみたいと思います。

https://github.com/clux/muslrust
https://zenn.dev/tkithrta/articles/cb91f6c8246d9a

ビルド

まずはWadoをGitでcloneします。

git clone https://github.com/wado-lang/wado.git

wadoディレクトリに移動して、Dockerfileを作成します。

cd wado
touch Dockerfile

後はDockerfileを書いてビルドするだけです。

Dockerfile
FROM clux/muslrust:stable AS builder

WORKDIR /volume
COPY . .

ENV CARGO_PROFILE_RELEASE_OPT_LEVEL=s
ENV CARGO_PROFILE_RELEASE_PANIC=abort
ENV CARGO_PROFILE_RELEASE_LTO=true
ENV CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1
ENV CARGO_PROFILE_RELEASE_STRIP=true
RUN rustup target add x86_64-unknown-linux-musl
RUN cargo build -r --target=x86_64-unknown-linux-musl -p wado-cli

FROM gcr.io/distroless/static-debian13

WORKDIR /
COPY --from=builder /volume/target/x86_64-unknown-linux-musl/release/wado .

ENTRYPOINT ["/wado"]

バイナリサイズを減らしつつ、muslrustとdistrolessのマルチステージビルドでDockerイメージを作成します。

ここで注意したいのが、cargo build -rでビルドするとwado-bundledで設定されているlib.crate-type = ["cdylib"]build.target = "wasm32-unknown-unknown"を引きずってしまい、muslrustのx86_64-unknown-linux-muslでうまくビルドできないというところです。

どうやらwado-bundledはバンドルされたWASMに関する組み込み関数を使うためにオプションとして提供されているみたいなので、Wadoランタイムを動かすうえで必須というわけではないようです。

そのためrustup target add x86_64-unknown-linux-muslを行った後に、cargo build -r--target=x86_64-unknown-linux-musl-p wado-cliを指定しましょう。

これでwado-cliと、その依存関係であるwado-compilerのみがビルドされます。

docker build -t wado .

Wadoのビルドが終わるまでしばらく待ちます。

$ docker run --rm wado --version
wado 0.1.0
touch hello.wado
hello.wado
#!/usr/bin/env -S wado run
use { println, Stdout } from "core:cli";

export fn run() with Stdout {
    println("Hello, World!");
}
$ docker run --rm -v "$PWD/hello.wado:/hello.wado" wado run hello.wado
Hello, World!

無事musl libcのWadoランタイムが使えるようになりました。

後はビルドしたバイナリとDockerイメージを保存しておくだけです。

docker container create wado
docker container cp "$(docker ps -aq | head -1):/wado" wado
docker container rm "$(docker ps -aq | head -1)"
docker image save wado | gzip > wado.tar.gz

もちろんこのバイナリとDockerイメージは様々な環境で動かすことができます。

$ ./wado run hello.wado
Hello, World!
$ docker image load < wado.tar.gz
$ docker run --rm -v "$PWD/hello.wado:/hello.wado" wado run hello.wado
Hello, World!

ダイエット

muslrustでビルドしたおかげで、ランタイムのバイナリサイズは16.6MB、Dockerイメージサイズは18.4MB、Dockerイメージを圧縮すると6.94MBになりました(2026年2月4日更新)。

$ ls -lah
total 24M
drwxr-xr-x 1 root root   30 Feb  4 14:45 .
drwxrwxr-x 1 root root   68 Feb  4 14:45 ..
-rwxr-xr-x 1 root root  17M Feb  4 14:45 wado
-rw-r--r-- 1 root root 7.0M Feb  4 14:45 wado.tar.gz

さらにダイエット

2026年2月4日、Wasmtimeのドキュメントを読んでいたところRUSTFLAGS="-C strip=symbols"より良い環境変数があることを知ったのでGemini 3 Pro Previewに確認してDockerfileとダイエット結果を更新しました。

https://docs.wasmtime.dev/examples-minimal.html
https://doc.rust-lang.org/cargo/reference/profiles.html
https://github.com/johnthagen/min-sized-rust

Discussion