TL;DR
- Docker Desktop の標準のランタイムは WebAssembly Component を実行できないので、設定で containerd のイメージストアと Wasm のサポートを有効にする。
FROM scratchに Wasm ファイルをコピーしたイメージを--platform wasi/wasmでビルドし、Wasm 用のランタイムを指定してdocker runで実行する。
内容
WebAssembly Component の有効化
Docker は階層構造のアーキテクチャをとっている。クライアントは GUI(Docker Desktop)や CLI(docker)である。高レベルランタイムは、クライアントからのリクエストを受け取り、必要に応じて低レベルランタイムを起動する。低レベルランタイムは、実際にコンテナを起動する。
2024 年 11 月 1 日時点では、Docker Desktop の標準の高レベル・低レベルランタイムは WebAssembly Component の実行に対応していない。そのため、設定画面でランタイムを切り替える。
- 右上の歯車アイコンから設定画面を開く
- General で「Use containerd for pulling and storing images」にチェックを入れ、「Apply & restart」をクリックする。これで WebAssembly を実行するための高レベルランタイムが有効になる
- Features in development で「Enable Wasm」にチェックを入れ、「Apply & restart」をクリックする
コンテナイメージの作成と実行
この方法が使えるのは、wasi:cli/command World を実装した Component だけである。第3章で作った Component を使う。
# 親イメージを持たないベースイメージを作る
FROM scratch
# 実行する Wasm ファイルをイメージにコピーする
COPY ./target/wasm32-wasip1/release/hello-wasi-cli.wasm /hello-wasi-cli.wasm
# イメージの実行時に、コピーした Wasm ファイルを実行する
ENTRYPOINT ["/hello-wasi-cli.wasm"]イメージは docker buildx build で作る。成功すると、Docker Desktop の Images に表示される。
docker buildx build --platform wasi/wasm -t hello-wasi-cli .通常のコンテナイメージと同じく docker run で実行する。--runtime で、Component の実行に Wasmtime を使うよう指定する。
docker run --rm --runtime=io.containerd.wasmtime.v1 --platform=wasi/wasm hello-wasi-cliSpin アプリケーションのイメージ作成と実行
Spin のプロジェクトも、ほぼ同じ手順でイメージにできる。違いは、spin.toml と、アプリケーションで使う Wasm ファイルをすべてコピーし、ENTRYPOINT に spin.toml を指定する点である。
FROM scratch
COPY spin.toml /spin.toml
COPY echo.wasm /echo.wasm
COPY first-glitch-art-api.wasm /first-glitch-art-api.wasm
COPY hello_wasi_http.wasm /hello_wasi_http.wasm
ENTRYPOINT ["/spin.toml"]docker buildx build --platform wasi/wasm -t hello-world-with-spin .
docker run \
--runtime=io.containerd.spin.v2 \
--platform=wasi/wasm \
-p 3000:80 \
hello-world-with-spinランタイムには io.containerd.spin.v2 を使う。これは Spin アプリケーション用のランタイムで、ENTRYPOINT に指定された spin.toml を読み、その設定に従って Component を起動する。
コンテナの中で起動した Spin アプリケーションは、コンテナの実行環境から切り離されたサンドボックスで動く。そのため、サンドボックス内のポート番号と、コンテナを実行している環境のポート番号を対応付ける必要がある。上のコマンドでは -p 3000:80 で対応付けており、3000 番ポートへのアクセスが、サンドボックス内のプログラムの 80 番ポートに転送される。ブラウザや CLI からアクセスするときも 3000 番ポートを指定する。
$ curl localhost:3000/hello-world
Hello, world!