WASM runtime|platform?

Fly seems a good candidate for hosting WASM apps given it’s ability to spin up microVMs rapidly, private networking, anycast addressing…

What’s missing is a platform that makes deploying WASM apps simple and enabling some foundational integration (through WASI?); at a minimum perhaps an HTTP server and acess to a key-value service

Microsoft’s (DeisLab’s) Krustlet (a Rust-based Kubelet for running WASM as part of a Kubernetes cluster) uses OCI containers to distribute WASM apps (see:
OCI distribution).

Fly could accept these containers and a variant of fly.toml to have sufficient data to deploy a distributed WASM runtime.

Perhaps there’s potential in a collaboration with wasmCloud?

WASM out-of-browser is unserved by the dominant Cloud Platforms and I sense an opportunity for clever, nimbler others.

1 Like

We’ve thought about this! What’s missing from our stack is a way to distribute files/code/whatever to running VMs. It’s all very Docker heavy, and once you have app code in Docker you may as well just run a new VM.

How would you want wasm / script / etc app deploys to work?

Thanks for taking the time to reply!

My understanding is that Fly “unwinds” (OCI) Docker container images and deploys the tarballs directly to Firecracker VMs atop a Linux kernel.

I was thinking that a parallel model would detect and unwind (OCI) WASM container images and deploy the … waves hands… WASM modules… to Firecracker VMs atop a Linux kernel that includes a WASM|WASI runtime.

While kicking the tires of Fly last week, the blog post Deploy a Sat Serverless function with to Fly.io was published. This simple wasm function written in Go makes another nice example of how to run workloads on fly.io.
But I wondered if the manual steps to build and run the container could be baked into a Dockerfile for remote builds on Fly so that wasm functions can be built from Go source and started with a single command.
Here is my first stab at just the last steps of a Dockerfile for remote builds on Fly.
‘flyctl launch --name sha18’’ just grabs the compiled sha256.wasm binary from the GitHub repo and deploys it with ‘sat’:

FROM suborbital/sat:latest

# copy wasm from local git tree 
# https://github.com/wasm-builders/sat-on-fly/blob/main/sha256/sha256.wasm
COPY ./sha256.wasm .

# otherwise, sat will listen on random high port, see
# Publish your Runnables on wapm.io
#  https://www.wasm.builders/k33g_org/publish-your-runnables-on-wapmio-49k0
# SAT_HTTP_PORT=8080 sat https://registry-cdn.wapm.io/contents/k33g/forty-two/1.0.0/forty-two.wasm

ENTRYPOINT [ "sat", "./sha256.wasm" ]

It returns the test vector for the example shown in the Blog post:

rs@penguin:~/fly.io/wasmSHA256$ curl -d '👋 Hello World 🌍' https://sha18.fly.dev

As a novice to both Fly and Dockerfile, I would be happy to learn from others how to add the missing steps to the Dockerfile that compile the Go source into the wasm function, e.g. how to do this properly :slight_smile:

$ fly logs
2022-05-02T05:35:49Z runner[525e05fc] fra [info]Starting instance
2022-05-02T05:35:49Z runner[525e05fc] fra [info]Configuring virtual machine
2022-05-02T05:35:49Z runner[525e05fc] fra [info]Pulling container image
2022-05-02T05:35:52Z runner[525e05fc] fra [info]Unpacking image
2022-05-02T05:35:53Z runner[525e05fc] fra [info]Preparing kernel init
2022-05-02T05:35:54Z runner[525e05fc] fra [info]Configuring firecracker
2022-05-02T05:35:54Z runner[525e05fc] fra [info]Starting virtual machine
2022-05-02T05:35:54Z app[525e05fc] fra [info]Starting init (commit: 252b7bd)...
2022-05-02T05:35:54Z app[525e05fc] fra [info]Preparing to run: `sat ./sha256.wasm` as sat
2022-05-02T05:35:54Z app[525e05fc] fra [info]2022/05/02 05:35:54 listening on [fdaa:0:5f91:a7b:66:525e:5fc:2]:22 (DNS: [fdaa::3]:53)
2022-05-02T05:35:54Z app[525e05fc] fra [info]{"log_message":"(W) configured to use HTTP with no TLS","timestamp":"2022-05-02T05:35:54.995310031Z","level":2,"app":{"sat_version":"v0.1.2"}}
2022-05-02T05:35:55Z app[525e05fc] fra [info]{"log_message":"(I) starting sha256 ...","timestamp":"2022-05-02T05:35:55.016314045Z","level":3,"app":{"sat_version":"v0.1.2"}}
2022-05-02T05:35:55Z app[525e05fc] fra [info]{"log_message":"(I) serving on :8080","timestamp":"2022-05-02T05:35:55.016479725Z","level":3,"app":{"sat_version":"v0.1.2"}}
2022-05-02T05:36:07Z app[525e05fc] fra [info]{"log_message":"(I) POST /","timestamp":"2022-05-02T05:36:07.616963188Z","level":3,"app":{"sat_version":"v0.1.2"},"scope":{"request_id":"9089130d-4748-4028-b006-15164b1ee44d"}}
2022-05-02T05:36:07Z app[525e05fc] fra [info]{"log_message":"(I) POST / completed (200: OK) in 2ms","timestamp":"2022-05-02T05:36:07.618655989Z","level":3,"app":{"sat_version":"v0.1.2"},"scope":{"request_id":"9089130d-4748-4028-b006-15164b1ee44d"}}

P.S. The size of the image deployed by Fly is:
Image size: 49 MB

You’d have better success asking these on Stackoverflow / Suborbital’s dev channels, tbh, as building wasm in Docker isn’t really specific to Fly, at all.

That said, if you’re bought in to suborbital’s ecosystem, then ref this post (and for background see these 1, 2, 3) which is specific to their wasm-as-FaaS toolchain and runtime.

Building Golang in Docker is executing go build / go test / go get / go install commands as you would in your shell.

Specifically, per the articles shared above, to target wasm with go, one would exec:

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
GOOS=js GOARCH=wasm go build -o sha256.wasm

which (I haven’t tested) but for SAT translates to:

# create a build-stage "builder" Docker img w subo:latest
FROM suborbital/builder-tinygo:dev AS builder

# setup work dir in builder
RUN             mkdir /app
WORKDIR         /app

# copy contents of current dir in host into Docker img
COPY . .

# run other commands as needed
# ...

# compile the current go module (ex: sha256.go) to wasm w subo
subo build . --native

# create a deploy-stage "runner" Docker img w suborbital sat
FROM suborbital/sat:latest AS runner

# copy build output from builder into runner's root dir
COPY --from=builder /app/sha256.wasm /


ENTRYPOINT [ "sat", "./sha256.wasm" ]

If not, you’d have to build with subo outside of Dockerfile (that would then contain only the runner stage).

A better soln would be if someone codes up a “fly deployer” (like so).

1 Like