Wasm Component binary を Docker Desktop か Podman Desktop か Rancher Desktop か k8s で動かしたい

コンテナ事情がわからなすぎるのだけれど、Scala から wasi:http/proxy
を使った echo server 実装できたので、これをLinuxコンテナを介さずに実行したい。
環境はM2 Macなんですが...やっぱLinuxがないとダメ?
Docker Desktop, Rancher Desktop, Podman Desktop
colima でも出来そうだけどなんか大変そうだ
Wasm OCI artifact を作っておく
Wasm OCI artifact の定義はこれかな https://github.com/cncf/tag-runtime/blob/7d0be31ca4f6ac9468b23f9841549d30cfd7077e/wgs/wasm/deliverables/wasm-oci-artifact/index.md
github container registry にアップロードしよう。write:packages
で access token 作る https://github.com/settings/tokens/new
https://github.com/sunfishcode/hello-wasi-http これをビルドして...
$ cargo component build --target wasm32-wasip2 -r
Creating component target/wasm32-wasip1/release/hello_wasi_http.wasm
$ wasm-tools print target/wasm32-wasip1/release/hello_wasi_http.wasm | head -n 5
(component
(type (;0;)
(instance
(export (;0;) "error" (type (sub resource)))
)
$ wkg oci push -u tanishiking -p <access_token> ghcr.io/tanishiking/hello-wasi-http:latest target/wasm32-wasip1/release/hello_wasi_http.wasm
pushed: ghcr.io/tanishiking/hello-wasi-http:latest
digest: sha256:2eb7107596f175c77f76976ea5aed13a376cc100571f0a8d04667efd7d6455b7
アップロードしたのはこちら: https://github.com/users/tanishiking/packages/container/package/hello-wasi-http
参考にした

Docker Desktop
$ docker run --rm --runtime=io.containerd.wasmtime.v1 --platform=wasi/wasm secondstate/rust-example-hello:latest
Unable to find image 'secondstate/rust-example-hello:latest' locally
latest: Pulling from secondstate/rust-example-hello
269cd1915aa9: Pull complete
Digest: sha256:0e9edda42141012ed92fb65ee20de32f9469f1cd83e0131adf110eb4215f85f5
Status: Downloaded newer image for secondstate/rust-example-hello:latest
docker: Error response from daemon: failed to create task for container: failed to start shim: failed to resolve runtime path: runtime "io.containerd.wasmtime.v1" binary not installed "containerd-shim-wasmtime-v1": file does not exist
Run 'docker run --help' for more information
containerd-shim-wasmtime-v1
Docker が勝手に shims インストールしてくれるって話かと思った
Docker Desktop downloads and installs the following runtimes:
io.containerd.slight.v1
io.containerd.spin.v2
io.containerd.wasmedge.v1
io.containerd.wasmtime.v1
io.containerd.lunatic.v1
io.containerd.wws.v1
io.containerd.wasmer.v1
インストールしてくれそうだが...
これと同じ症状。
そもそも runwasi が MacOS サポートしてないんだから、動かない? https://github.com/containerd/runwasi/issues/42
いや、Docker Desktop は Linux VM を立ててその上でコンテナを動かすという理解なので、動いてほしいけどなぁ

Podman Desktop インストールしたけど CLI はついて来なかった? ので brew install podman
した。
$ podman version
Client: Podman Engine
Version: 5.5.0
API Version: 5.5.0
Go Version: go1.24.3
Built: Wed May 14 03:59:13 2025
Build Origin: brew
OS/Arch: darwin/arm64
Server: Podman Engine
Version: 5.5.0
API Version: 5.5.0
Go Version: go1.23.8
Git Commit: 0dbcb51477ee7ab8d3b47d30facf71fc38bb0c98
Built: Tue May 13 09:00:00 2025
OS/Arch: linux/arm64
Podman はVM(Podman Machine)というLinux VMの中でコンテナを実行
When using containers with Podman on macOS or Windows, you have a virtual machine called a "Podman machine" that is executing a Linux environment. We need to add support for Wasm inside this Linux environment. Podman is using the crun project as its OCI runtime, so crun needs to be able to run or delegate execution to Wasm runtimes. Lucky for us, crun supports Wasm execution.
https://podman-desktop.io/blog/wasm-workloads-on-macos-and-windows-with-podman
Many people do not realize that containers are really Linux. As such, Linux containers cannot run natively on macOS. Therefore, the containers must run in a Linux virtual machine (VM), and a Podman client interacts with that VM. This is in line with all solutions for running containers on macOS.
https://www.redhat.com/en/blog/podman-mac-machine-architecture
とりあえずデモを動かす
$ podman run --platform wasi/wasm quay.io/podman-desktop-demo/wasm-rust-hello-world
!... Hello Podman wasm World ...!
.--"--.
/ - - \
/ (O) (O) \
~~~| -=(,Y,)=- |
.---. /` \ |~~
~/ o o \~~~~.----. ~~
| =(X)= |~ / (O (O) \
~~~~~~~ ~| =(Y_)=- |
~~~~ ~~~| U |~~
Project: https://github.com/containers/podman
Website: https://podman.io
Documents: https://docs.podman.io
Twitter: @Podman_io
でもこれ明らかにwasip1だよね https://github.com/redhat-developer/podman-desktop-demo/tree/main/wasm/rust-hello-world
Podman desktop で ghcr にログインしておいて...
$ podman run --platform wasi/wasm ghcr.io/tanishiking/hello-wasi-http:latest
Trying to pull ghcr.io/tanishiking/hello-wasi-http:latest...
Error: internal error: unable to copy from source docker://ghcr.io/tanishiking/hello-wasi-http:latest: parsing image configuration: unsupported image-specific operation on artifact with type "application/vnd.wasm.config.v0+json"
crun が(?) application/vnd.wasm.config.v0+json
に対応してないから使えないのかな? そもそも podman がいってる Wasm OCI image って何? これ? https://github.com/solo-io/wasm/blob/master/spec/README.md

Rancher Desktop
https://github.com/containerd/runwasi/releases/tag/containerd-shim-wasmtime%2Fv0.6.0 から containerd-shim-wasmtime をインストールする。aarch64
と x86
どっちにすればいいんだろう、ホストがaarch64だしそっちから
$ mkdir ~/Library/Application\ Support/rancher-desktop/containerd-shims
$ cp containerd-shim-wasmtime-aarch64-linux-musl/containerd-shim-wasmtime-v1 ~/Library/Application\ Support/rancher-desktop/containerd-shims/
これでRancher Desktopを立ち上げる
あの... nerdctl
入らないんですが... -> PATH 設定を Manual にすると ~/.rd/bin
に nerdctl 入ってた。よしよし
https://github.com/containerd/nerdctl/blob/main/docs/registry.md#github-container-registry-ghcr nerdctl から ghcr に login して
$ nerdctl login ghcr.io -u tanishiking
$ nerdctl run --rm --runtime=io.containerd.runwasi.v1 --name hello-wasi-example ghcr.io/tanishiking/hello-wasi-http:latest
FATA[0002] unknown media type "application/vnd.wasm.config.v0+json"
Error: exit status 1
う〜ん、何故
moby backend にした場合はこれ、なんでやねん???
$ docker run --rm --runtime=io.containerd.wasmtime.v1 --platform=wasi/wasm ghcr.io/tanishiking/hello-wasi-http:latest
Unable to find image 'ghcr.io/tanishiking/hello-wasi-http:latest' locally
latest: Pulling from tanishiking/hello-wasi-http
Digest: sha256:2eb7107596f175c77f76976ea5aed13a376cc100571f0a8d04667efd7d6455b7
Status: Image is up to date for ghcr.io/tanishiking/hello-wasi-http:latest
docker: Error response from daemon: No such image: ghcr.io/tanishiking/hello-wasi-http:latest

kubernetes (kind)
$ system_profiler SPHardwareDataType
Hardware:
Hardware Overview:
Model Name: MacBook Pro
Model Identifier: Mac14,7
Model Number: Z16R000S2J/A
Chip: Apple M2
Total Number of Cores: 8 (4 performance and 4 efficiency)
Memory: 16 GB
System Firmware Version: 11881.121.1
OS Loader Version: 11881.121.1
Serial Number (system): JXGD2QK61V
Hardware UUID: EA3516EF-EA8F-555A-AE7B-887568CB2AD7
Provisioning UDID: 00008112-001819D634A3C01E
Activation Lock Status: Enabled
$ uname -m
arm64
runwasi の quickstart with Kubernetes 試してみよう
https://github.com/containerd/runwasi/releases から containerd-shim-wasmtime-aarch64-linux-musl.tar.gz
をダウンロード、展開して /usr/local/bin/containerd-shim-wasmtime-v1
にコピーして chmod +x
$ cat kind-config.yaml
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: runwasi-cluster
nodes:
- role: control-plane
extraMounts:
- hostPath: /usr/local/bin/containerd-shim-wasmtime-v1
containerPath: /usr/local/bin/containerd-shim-wasmtime-v1
$ kind create cluster --name runwasi-cluster --config kind-config.yaml
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d776f952e99d kindest/node:v1.33.1 "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes 127.0.0.1:55740->6443/tcp runwasi-cluster-control-plane
runwasi-cluster-control-plane
の /etc/containerd/config.toml
に containerd 設定を書き込んで、再起動
$ cat << EOF | docker exec -i runwasi-cluster-control-plane tee /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.wasm]
runtime_type = "io.containerd.wasmtime.v1"
EOF
$ docker exec runwasi-cluster-control-plane systemctl restart containerd
# deploy.yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: wasm
handler: wasm
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasi-demo
spec:
replicas: 1
selector:
matchLabels:
app: wasi-demo
template:
metadata:
labels:
app: wasi-demo
spec:
runtimeClassName: wasm
containers:
- name: demo
image: ghcr.io/containerd/runwasi/wasi-demo-app:latest
$ kubectl --context kind-runwasi-cluster apply -f deploy.yaml
$ kubectl --context kind-runwasi-cluster get pods
NAME READY STATUS RESTARTS AGE
wasi-demo-6d48f6979f-bplf4 0/1 ContainerCreating 0 6m25s
$ kubectl --context kind-runwasi-cluster logs -l app=wasi-demo
Error from server (BadRequest): container "demo" in pod "wasi-demo-6d48f6979f-bplf4" is waiting to start: ContainerCreating
$ kubectl describe pod -l app=wasi-demo
Name: wasi-demo-6d48f6979f-bplf4
Namespace: default
Priority: 0
Runtime Class Name: wasm
Service Account: default
Node: runwasi-cluster-control-plane/172.18.0.2
Start Time: Wed, 04 Jun 2025 09:26:25 +0900
Labels: app=wasi-demo
pod-template-hash=6d48f6979f
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Controlled By: ReplicaSet/wasi-demo-6d48f6979f
Containers:
demo:
Container ID:
Image: ghcr.io/containerd/runwasi/wasi-demo-app:latest
Image ID:
Port: <none>
Host Port: <none>
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-7zr6j (ro)
Conditions:
Type Status
PodReadyToStartContainers False
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
kube-api-access-7zr6j:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m35s default-scheduler Successfully assigned default/wasi-demo-6d48f6979f-bplf4 to runwasi-cluster-control-plane
Warning FailedCreatePodSandBox 3m34s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "18c1a680837ab9690d40bc8e5f70c83122ae908149f733e2f97835c79b35230c": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 3m21s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "6e7420b360feec3532b90f681fa0d74883e7945fcf1b6ace83214d1f606fb3fb": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 3m7s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "3c4781367cde6554a00a65a55f98ca63c5d1e7afa4dfda630ae4268d5425b92b": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 2m52s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "81db1c659ee3fb2b88adeb829ef1f2c175ec1032ddeb4dee3ca9cf7b329af3ec": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 2m39s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "5c342538c1028a432b1b5516f5576e149a6c7bd2bbe7295cd89b70ae6a355ade": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 2m26s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "d4dea10f255e271f50522be576a5743182cab39ee8e8c8808f805fe7d391e3e0": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 2m15s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "550d4c6aead977349f4c1a8e0ba2f37d8cc34428d39b3276bfa6ed80ee83456e": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 2m kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "54bcfa907c2b5fb6e3066f0f1b341ea10d251e6c7a8c39be397d65d009698823": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 108s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "2f75d74a5fc6e91b093004ca40163b534c63fb1bcab4496c49ab216280e4ffc4": no runtime for "wasm" is configured
Warning FailedCreatePodSandBox 5s (x8 over 97s) kubelet (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = unable to get OCI runtime for sandbox "1a969db3abb0e6f43eb68d857735841653d60954bbde84f80259b8dfe9053bdf": no runtime for "wasm" is configured
no runtime for "wasm" is configured
うーむ
kind の container に入って containerd config
叩いてみたけど、普通にruntime設定できてなくないか?
こういうこといわれてるし
WARN[0000] Ignoring unknown key in TOML for plugin error="strict mode: fields in the document are missing in the target struct" key=containerd plugin=io.containerd.grpc.v1.cri
WARN[0000] Ignoring unknown key in TOML for plugin error="strict mode: fields in the document are missing in the target struct" key="containerd runtimes" plugin=io.containerd.grpc.v1.cri
WARN[0000] Ignoring unknown key in TOML for plugin error="strict mode: fields in the document are missing in the target struct" key="containerd runtimes wasm" plugin=io.containerd.grpc.v1.cri
WARN[0000] Ignoring unknown key in TOML for plugin error="strict mode: fields in the document are missing in the target struct" key="containerd runtimes wasm options" plugin=io.containerd.grpc.v1.cri
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.wasm]
runtime_type = "io.containerd.wasmtime.v1"
EOF
これだといけたわ。(ほかの containerd config dump
設定をまねた)

$ docker exec runwasi-cluster-control-plane containerd --version
containerd github.com/containerd/containerd/v2 v2.1.1 cb1076646aa3740577fafbf3d914198b7fe8e3f7
containerd v2 から toml をフォーマット変わったのかな、とりあえず runwasi に報告した

spec:
runtimeClassName: wasm
containers:
- name: demo
image: ghcr.io/tanishiking/hello-wasi-http:latest
これだと
Normal Pulled 2s (x2 over 14s) kubelet (combined from similar events): Successfully pulled image "ghcr.io/tanishiking/hello-wasi-http:latest" in 627ms (627ms including waiting). Image size: 90554 bytes.
Warning Failed 2s (x2 over 14s) kubelet (combined from similar events): Error: failed to generate container "d749477ff3e9b92d3d17b85870ebe42532fb3451d3ebfe4aec8caebd2bce95bb" spec: failed to generate spec: no command specified
spec:
runtimeClassName: wasm
containers:
- name: demo
image: ghcr.io/tanishiking/hello-wasi-http:latest
command: [""]
これならok
kubectl port-forward wasi-demo-65c85ddd56-hgtpg 8080:8080
$ curl http://localhost:8080
Hello, wasi:http/proxy world!

肝心のscalaから生成したバイナリをrunwasiから実行できなかった

AKS 以前は kruslet 使って Wasm workload 提供してたけど、なくなったらしい(runwasiは????!!)
次は spinkube や wasmCloud 使ってねとのこと

チュートリアルを直した
のために wasmtime をv33に上げた
wasmgc を enable した wasmtime を使った shim のビルドを公開した。これで wasmgc 使ったバイナリをrunwasiで動かせる