.NET · Architecture · containerd · docker · OCI · runc · WASI · WASM

Exploring WASM, WASI with .net7 & Docker

Web Assembly aka WASM is currently gaining a lot of attention into the container community – for legit reasons! WASM is a web-optimized code format that significantly improve web application performances running on browsers. However, it is gaining more and more attention in the container world lately, because of its sandbox/isolation hence – safety, near-native speed of executions, OS agnostic, and typically extremely small footprints in terms of sizes.

 WebAssembly System interface (WASI) project allows writing and compiling code for only one, obviously virtual, but complete operating system (emulating the syscalls with certain adherences). In this way, even if you loaded it on ten different platforms, a binary Wasm module calling a certain WASI function would still get – from the runtime that launched it – a different binary object every time. But since all those objects would interact with that single Wasm module in exactly the same way, it would not matter!

https://wasmlabs.dev/articles/docker-without-containers/
Images source: https://wasmlabs.dev/articles/docker-without-containers/

The following are few key strengths of WASM:

  • Fast – WASM apps executes near-native speed via the JIT/AOT capabilities of most runtimes. Noticeably faster than even a container startup time.
  • Standard – it is widely adopted standard across the communities.
  • Secure – WASM runtime is sandboxed and only can access resources that are explicitly allowed.
  • Portable – Works across major runtimes for most CPUs (x86, ARM etc.) and most OS like Linux (all POSIX), macOS, Windows etc.
  • Polyglot – WASM doesn’t force to any specific language, one can develop the application in any language as they like, and comile it down to WASM.

Let’s see how we can create a OCI image using Docker and run it.

Configuring Docker

You would need Docker desktop 4.15.0 or later versions for this. Docker WASI is currently on BETA, hence shouldn’t be used in production environment.

We need to activate a beta flag that tell Docker to use containerd for docker images. We can do that from Docker desktop as shown in the picture below:

How Docker runs a WASM image? Docker is leveraging containerd, as it provides the ability to use both OCI-compatible artifacts and containerd shims. Docker uses the OpenSource WasmEdge project to create a containerd shim. This shim extracts the Wasm module from the OCI artifact and runs it using the WasmEdge runtime. Finally, the Wasm runtime enables the use of this new shim.

Image source: https://www.docker.com/blog/docker-wasm-technical-preview/

Creating .net7 console application

For a quick demo, let’s create a simple dotnet application. We can use the dotnet CLI for that. (We need to make sure that NET 7 SDK is installed on the box).

dotnet new console -o SampleApp

Next, we need to compile this application, but we want to produce a WASM output than typically produced DLLs. For that we will need to add a reference to dotnet add package Wasi.Sdk --prerelease. Let’s use the dotnet CLI again for that:

dotnet add package Wasi.Sdk --prerelease

Now, if we build the application:

dotnet build

We notice that the bin folder contains a .wasm file.

Build OCI image

In order to build an OCI image for the above application we will use the following Dockerfile:

FROM scratch
COPY ./SampleApp/bin/debug/net7.0/SampleApp.wasm /SampleApp.wasm
ENTRYPOINT [ "SampleApp.wasm" ]

Buidling is trivial, we will use docker CLI from command line:

docker build --platform wasi/wasm -t moimhossain/dotnet-wasi-helloworld:alpha .

We need to provide the --platform wasi/wasm switch while building.

Run it

Running this image also requires specifying the runtime switch and platform switch.

docker run --rm --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm moimhossain/dotnet-wasi-helloworld:alpha

Which produces our desired output, printing Hello world into the console.

We can now push/pull this image like any other Docker images.

If we run docker images to see these images, we see the image is about 3.6MB – that is significantly smaller than any regular container images.

> docker images

REPOSITORY                                       TAG       IMAGE ID       CREATED             SIZE
moimhossain/dotnet-wasi-helloworld   alpha     23a53cc7f78c   About an hour ago   3.63MB

Conclusion

As of today, WASM/WASI with Docker is in beta stage and rough on the edges. However, it is easy to recognize the high potential of this development. I am excited and looking forward to observing how things evolve in coming future!

The sample code can be found in GitHub. Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s