WASM+Docker Hello World
Tags: docker, webassembly, rust
Published: 2023-01-27 13:52:22

### WASM Hello World App with Rust and Docker Desktop

WebAssembly (WASM) is a binary instruction format for a stack-based virtual machine that is designed to be fast and efficient. It is a low-level assembly-like language that runs in the browser and provides a way to execute code at near-native speeds. WASM is supported by all major web browsers, including Chrome, Firefox, Safari, and Edge.

WebAssembly System Interface (WASI) is an interface that allows WebAssembly code to access the underlying operating system and file system. It provides a standardized set of system calls for WebAssembly modules to interact with the host environment. This allows WebAssembly code to be run in the backend.

> In short, if WASM is JavaScript, WASI is Node.js.

Another important aspect of WASM is that it is language-agnostic, which means that code written in a variety of programming languages, such as Rust, C++, or C can be compiled to WASM and run in the browser. This provides developers with more options for building web applications and allows them to take advantage of the strengths of different languages.

## TL;DR
In this piece, we’re going to create a Hello World app using Rust, compile it into a WASM binary, and run it using Docker Desktop.


![WASM + Docker Hello World!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wx6umnilz22wvo7cip3.png)

## Install Rust and WASM Package

To get started, you’ll need to have the Rust programming language installed on your computer. You can install Rust by following [the instructions on the official website](https://www.rust-lang.org/tools/install):

```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

It installs Rust together with its package manager, Cargo. After installation, I had to run the following command to update the `$PATH` variable:

```shell
source "$HOME/.cargo/env"
```

Now you can verify Rust is installed:

```shell
rustc --version
```

My output was the following:

```
rustc 1.66.1 (90743e729 2023-01-10)
```

## Create the Project

Once you have everything set up, you can create a new Rust project. First, change to a directory where you would gather your Rust projects, and then run the following command:

```shell
cargo new hello-wasm
```

This will create a new directory called “hello-wasm” with the basic structure of a Rust library. Git is already initialized there, but there is no commit yet.

The `src/lib.rs` already has a Hello World code:

```rust
fn main() {
    println!("Hello, world!");
}
```

You can build this app _normally_ using:

```shell
cargo build
```

This will create a binary file and put it under `target/dev`. You can execute it directly:

```shell
./target/debug/hello-wasm
```

This binary file is built for your machine and is platform-dependent.

## Build WASM Binary

Now, to build the project for a WASM runtime, we need to add a new target:

```shell
rustup target add wasm32-wasi
```

Then we can use this target in the build command:

```shell
cargo build --target wasm32-wasi
```

This command will create the WASM binary and put it under `target/wasm32-wasi`:

```
target
├── CACHEDIR.TAG
├── debug
│   ├── build
│   ├── deps
│   ├── examples
│   ├── hello-wasm
│   ├── hello-wasm.d
│   └── incremental
└── wasm32-wasi
    ├── CACHEDIR.TAG
    └── debug
        ├── build
        ├── deps
        ├── examples
        ├── hello-wasm.d
        ├── hello-wasm.wasm
        └── incremental
```

## Create Docker Image

Note that this is currently a preview feature and is only available on Docker Desktop. To be able to build or run WASM containers with your Docker Desktop, you first need to enable the “containerd pulling and storing feature” from the settings.

First, create a `Dockerfile` with the following content:

```dockerfile
# syntax=docker/dockerfile:1
FROM scratch
COPY ./target/wasm32-wasi/debug/hello-wasm.wasm /hello.wasm
ENTRYPOINT [ "hello.wasm" ]
```

Now build it using the following command:

```shell
docker buildx build --platform wasi/wasm32 -t hello-wasm .
```

Let’s check the Docker images currently available:

```shell
docker image ls
```

The output has this line:

```
hello-wasm    latest    e2f29c7ab88a    2 minutes ago    520kB
```

The image is created and is half a megabyte in size. Let’s run it using the following command:

```shell
docker run \ 
  --runtime=io.containerd.wasmedge.v1 \
  --platform=wasi/wasm32 \
  hello-wasm
```

It should say:

```
Hello, world!
```

## Final Words

WebAssembly offers a near-native performance and is platform-independent. Docker Desktop comes with WasmEdge runtime and allows one to wrap a WASM app into a Docker container and probably run it in a Docker Compose setup alongside non-WASM containers.

This article was originally published [on Medium](https://blog.devgenius.io/wasm-docker-hello-world-2ac6a456ddd4).