The current state of WASI in containers space

Guillaume Pierson
Guillaume PiersonSeptember 06, 2023
#serverless

WebAssembly is gaining a lot of traction in the container space. I wondered if I could use it in my daily work, and I found out that it was not that easy. Here is a summary of my findings.

What Is WASI?

WASI lets you run WebAssembly outside of the browser.

Technically, it's a standard that defines a system interface for WebAssembly. It is also designed to be sandboxed, so it is a good fit for containers. The advantage of using WASI is that you can run the same binary on any platform that that standard. Some of these platforms are described below.

It is also a good fit for serverless, as you can run the same binary on any serverless platform that supports WASI. It's the case for AWS, Azure, Fastly, Cloudflare, GCP should have support for it too, but I didn't find any documentation about it.

For containers, a WASI program doesn't need to include an operating system, so it makes the image smaller and more secure. Small containers are also faster to start than containers with an operating system.

WASI is sandboxed, so it adds a security layer to your application.

Current State Of WASI In Containers

Docker

Docker has technical preview of WASI support since July 2022. It is available in the experimental version of Docker Desktop only. You can enable it in the settings:

Docker experimental settings

Then you can run a WASI binary:

docker run --rm -it --platform wasm hello-world

It works well, but you need to use experimental features. It is not a big deal for local development, but it is not usable in production. Furthermore, Docker Desktop is not available for servers, so you really can't use it in production.

One of the advantages of Docker Desktop is also one of its disadvantages: it runs on a virtual machine. If you have Docker Engine and Docker Desktop, images are not shared between them as Docker Desktop runs on a virtual machine.

Wasmtime

Wasmtime is a WebAssembly runtime that supports WASI. It is written in Rust and open source. The development and maintenance are now supported by the Bytecode Alliance. Wasmtime was created by Fastly and Mozilla. Wasmtime can be installed on Linux, MacOS, and Windows. It is also available as a library for Rust, C, and C++.

WasmEdge

WasmEdge

WasmEdge is also a WebAssembly runtime for WASI. It's written in C++ and open source. WasmEdge runs on Linux, MacOS, Windows, Android and microkernels (view the complete list in the documentation). WasmEdge can call host functions, which can be useful if you want to call a native library.

It has also support for JavaScript and TypeScript, so it is a good fit for us.

But it is not that easy to use. All application needs to be compiled to WebAssembly. If it's a mere formality for Rust, is it harder for JavaScript and TypeScript. Some methods are not supported: I tried to run a simple react with server-side rendering, and it failed. Because of missing capabilities of the runtime, some methods were not implemented. I tried running a version of the adaptation of NodeJS that supports WASI called wasmedge_quickjs.wasm. QuickJS is a JavaScript engine written in C and compiled to WASM. Also, you will need to run WasmEdge in compiler mode to produce a version of quickjs in AOT. Otherwise, it will be too slow.

 wasmedgec wasmedge_quickjs.wasm wasmedge_quickjs_aot.wasm

In terms of security, being written in C++ is not a good thing in my opinion. It's more prone to memory leaks and buffer overflows.

Wasmer

Wasmer

Wasmer is a WebAssembly runtime that supports WASI. It is written in Rust.

Wasmer provides a near native performance. It is a good fit for serverless. It is also a good fit for containers.

Wasmer recently released a new version that provides support for POSIX calls. This implementation is called WASIX. You can now have access to multithreading, sockets, piping, and more.

For TypeScript Developers

At Marmelab we use TypeScript for most of our projects. So I wanted to know if I could use WASI with TypeScript.

Javy

Javy is a toolchain that runs JavaScript with WebAssembly. It is written in Rust and is open source. It's supported by Bytecode Alliance. It was previously developed by Shopify.

Compiling TypeScript to WebAssembly

I tried to compile TypeScript to WebAssembly. I found AssemblyScript, a subset of TypeScript that compiles to WebAssembly. the project is also open source.

The AssemblyScript syntax seems to be very similar to TypeScript, but in reality they are different languages. For example, you can't have a union type with a string and a number.

function foo(a: string | number) {
    // ...
}

As WebAssembly is strongly typed, you can't use the any type. You need to specify the type of each variable.

I tried to use a custom type but it is not supported.

type MyType = {
    a: string;
    b: i32;
}

AssemblyScript has support for generics, but due to missing capabilities, its use cases are limited.

function foo<T>(a: T): T {
    return a;
}

You have to extend an existing type. You can't create a new type from scratch.

For simple applications, we can overcome these limitations. But for a complex application with npm dependencies, it is not usable.

Conclusion

WASI is a great technology. It works well with Rust, but it is not the case for TypeScript/JavaScript. I hope that it will change in the future. I will keep an eye on it.

Our current development stack is based on TypeScript/JavaScript and thus is not ready to be used with WASI. For now, I will stick with Docker with an embedded operating system. Sooner or later, we will have to change our stack to use WASI for performance and security reasons.

If you want to use WASI, I recommend using Rust. It is a great language and it is well supported by WASI.

It was the first time I studied this topic, so I may have missed some things. There is a lot of information to process on that subject - it's a good sign! If you have any feedback, please let me know.

Did you like this article? Share it!