DockerでWebAssembly (Wasm) を実行:WasmEdgeで超軽量アプリをデプロイし、ミリ秒単位で起動する

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

DockerでWasmを5分で動かす

Docker Desktop (v4.15+)があれば、UbuntuやNode.jsのコンテナよりも速くWebAssembly (Wasm) アプリを実行できます。理論はさておき、まずはターミナルでこのコマンドを叩いてみましょう:

docker run --rm --runtime=io.containerd.wasmedge.v1 \
  --platform=wasi/wasm \
  secondstate/rust-learning:hello

結果はほぼ瞬時に表示されます。従来のコンテナでは、Dockerは数十MB ofイメージをプルし、名前空間を初期化し、ファイルシステムをマウントするのに数秒かかります。対照的に、Wasmは瞬時(通常10ms以下)に起動します。

このコマンドを動作させるには、Docker Desktopの Settings -> Features in development を開いてください。そこで、Use containerd for pulling and storing imagesEnable Wasm にチェックを入れてください。

なぜDockerにWebAssemblyが必要なのか?

「Dockerがうまく動いているのに、なぜわざわざWasmを追加して複雑にする必要があるのか?」とよく聞かれます。

答えはリソースの最適化にあります。以前、ECサイト向けのNode.jsマイクロサービスを構築した際、単純な税計算を行うだけのコンテナが200MBものRAMを消費していました。トラフィックが急増すると、CPUには余裕があるのにRAMが枯渇し、サーバーが次々とダウンしてしまいました。従来のコンテナは、軽量化されたOSプリミティブ(OS primitives)を丸ごと抱えているため、非常に重いのです。

WebAssemblyはこの問題を根本から解決します:

  • 極めてコンパクトなサイズ: .wasm ファイルは通常、数十KBから2MB程度です。400MBのNode.jsイメージと比較すると、飛躍的な進歩です。
  • 驚異的なスピード: WasmはOSをブートする必要がなく、ランタイム上で直接実行されます。起動速度は通常のコンテナの10倍から100倍高速です。
  • 安全なサンドボックス: デフォルトでWasmは完全に隔離されています。WASIインターフェースを通じて権限を与えない限り、ホストのファイルシステムやネットワークにはアクセスできません。

WasmEdge:超軽量な実行エンジン

Wasmがコンパイル済みのコードだとしたら、WasmEdgeはそのコードを実行するための仮想マシンです. Dockerのエコシステムにおいて、WasmEdgeは従来の runc に代わる runtime として機能します。

DockerとCNCFの協力により、現在ではLinuxコンテナとWasmコンテナを並行して管理できるようになりました。docker psdocker build といった慣れ親しんだコマンドをそのまま使え、ゼロから学び直す必要はありません。

実践:最初のWasmアプリをビルドしてデプロイする

Rustでアプリケーションを作成し、WasmにコンパイルしてDockerにパッケージングしてみましょう。Rustを知らなくても大丈夫です。以下の手順は非常にシンプルです。

ステップ1:Rustプロジェクトの初期化

cargo new hello-wasm
cd hello-wasm

src/main.rs ファイルを開き、以下のように修正します:

fn main() {
    println!("皆さんこんにちは、DockerでWasmがスムーズに動いています!");
}

ステップ2:WASIターゲットへのコンパイル

Rustをサーバー用の標準フォーマットにコンパイルするために、wasm32-wasi ターゲットを追加する必要があります:

rustup target add wasm32-wasi
cargo build --target wasm32-wasi --release

実行後、targetディレクトリに hello-wasm.wasm ファイルが生成されます。デプロイに必要なのはこれだけです。

ステップ3:「超軽量」なDockerfile

Wasm用のDockerfileには FROM pythonFROM node は必要ありません。サイズを最適化するために、空のイメージ(scratch)から開始します:

FROM scratch
COPY target/wasm32-wasi/release/hello-wasm.wasm /hello-wasm.wasm
ENTRYPOINT ["/hello-wasm.wasm"]

ステップ4:ビルドと実行

ビルド時には、プラットフォームとして wasi/wasm を指定する必要があります:

docker buildx build --platform wasi/wasm -t my-wasm-app .

成果を確認しましょう:

docker run --rm --runtime=io.containerd.wasmedge.v1 \
  --platform=wasi/wasm my-wasm-app

実践的なアドバイス:落とし穴に注意

非常に強力なツールですが、実戦に投入する際には以下の3つの重要なポイントに注意してください:

1. Wasmは「銀の弾丸」ではない

すべてのアプリをWasmに移行しようとしないでください。画像・動画処理、重い計算、あるいは小さなマイクロサービスには最適です。しかし、Linuxカーネルへの深い干渉が必要な場合や、複雑なCシステムライブラリを使用する場合は、依然として従来のDockerが最良の選択肢です。

2. ネットワークの制約

WASI環境におけるネットワーク通信はまだ制限があります。すべてのHTTPライブラリがすぐに動作するわけではありません。予期せぬ実行時エラーを避けるため、hyper-wasi のようにWasmEdgeに最適化されたライブラリを優先的に使用することをお勧めします。

3. 新しいデバッグ手法

docker exec -it bin/bash コマンドのことは忘れてください。WasmコンテナにはアクセスするためのOSが存在しないからです。デバッグは完全に stdout/stderr に依存します。より正確で詳細なログを記録する習慣をつけましょう。

結びに代えて

Docker上のWasmは、もはや単なる理論ではなく、実戦投入できるほど成熟しています。この組み合わせは、クラウドネイティブやエッジコンピューティングにおけるリソースコストの問題を根本的に解決します。

まずはシステムの最小限のサービスからWasmを試してみてください。Wasmの圧倒的な最適化能力のおかげで、毎月10万円かかっていたRAMの費用が1万円で済むようになるかもしれません。

この超軽量コンテナを使いこなし、開発を加速させてください!

Share: