Exploring Docker Hub’s WASM technical preview
WASM as an alternative to linux containers
Introduction
Docker has introduced WASM support which can run along side your containers. In this article, let us explore about how we can use this, and its implications.
To know about Docker, the platform, please refer to the following link:
Docker overview | Docker Documentation
WASM originally was conceived to bring native performance to the browsers. However, it has since grown and has shown promise outside the browser as well.
For details about what is WASM please read my earlier blog series on this:
WASM + WASI + WAGI + Web Assembly Modules in Rust
Prerequisites
To work with WASM in docker you would require docker desktop preview. If you have an existing version of docker desktop, please uninstall that and install the docker desktop tech preview using any of the following links relevant to your desktop OS:
- macOS Apple Silicon
- macOS Intel
- Windows AMD64
- Linux Arm64 (deb)
- Linux AMD64 (deb, rpm, tar)
Running the sample program
Once the docker desktop has been installed. We will first run the command provided by docker itself.
docker run -dp 8080:8080 \
--name=wasm-example \
--runtime=io.containerd.wasmedge.v1 \
--platform=wasi/wasm32 \
michaelirwin244/wasm-example
The parameters runtime=io.containerd.wasmedge.v1 and platform=wasi/wasm32 specifies to the docker engine that this particular container’s runtime must be the wasm containerd shim. In this case the shim is wasmedge. From the wasmedge website:
WasmEdge is a lightweight, high-performance, and extensible WebAssembly runtime for cloud native, edge, and decentralized applications.
It powers serverless apps, embedded functions, microservices, smart contracts, and IoT devices.
In general, there are other WASM runtimes available as well. In this case wasmedge is used. In the future we should be able to use other wasm runtimes.
Once you finish running this command, you should run
docker images
You should see
Here, we can see one the of the first key advantages that WASM brings to the table. SIZE of 1.57MB. This is key advantage over regular linux container images which are typically much bigger in size.
Next now let use check what is running, by executing
docker ps
Running the following would confirm that the web assembly is working as intended.
curl localhost:8080
Sending a POST request:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"hello":"world"}' \
localhost:8080/echo
Now that we are certain it is working, let us inspect the code for this example code to understand how we can build one ourselves.
Creating our own WASM module
This WASM module which we saw is running a loop and is listening for requests. Typically that is how Microservices would be built.
For our understanding, let us create our own simple WASM module.
First configure rust for WASM with
rustup target add wasm32-wasi
Then, create your own rust project:
cargo new wasm-docker
Once the new project is created, inspect the main.rs file:
fn main() {
println!("Hello, world!");
}
This should be enough for our purposes now. Now build the application
cargo build --target wasm32-wasi --release
Once, the build is complete the output will be available as the ./target/wasm32-wasi/release/wasm-docker.wasm
Creating a WASM image
Using the built wasm file we now build a OCI image from this WASM app. Create a Dockerfile and copy the following contents to it.
FROM scratch
COPY ./target/wasm32-wasi/release/wasm-docker.wasm /wasm-docker.wasm
ENTRYPOINT [ "wasm-docker.wasm" ]
Now build the image by running
docker buildx build --platform wasi/wasm -t wasm-docker:0.1 .
The key here is the platform argument. We are targeting this image to be built for WASI architecture rather than linux.
If all went well, when you run
docker images
You would be seeing the above image available.
Excellent, now it is time to
Run your WASM image
To run your docker image, issue the following command
docker container run --rm --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm32 wasm-docker:0.1
You should be seeing:
Success! The Hello, world! is printed from our program.
Implications
Though, this example is a simple one. What this would imply that we would able to build web services and deploy it to our existing tech stack.
If the same WASM module is deployed to a kubernetes cluster, that would mean we would be able to run our services at scale. WASM is making a lot of in-roads, in a few years I expect WASM to become a staple part of cloud native development.
If you liked this article, please clap and share. Until next time.