Developers can deploy, manage, and run lightweight WebAssembly applications in WasmEdge through Docker tools such as DockerHub and Cri-O.

WasmEdgeIs made up of
Hosted by CNCF (Cloud Native Computing Foundation)The WebAssembly runtime is an execution sandbox for edge computing applications.

Although WebAssembly was originally invented as a runtime for browser applications, its lightweight and high-performance sandbox design makes it an attractive choice for general-purpose application containers.

If we had WASM + WASI in 2008, we wouldn’t have started Docker at all. — Solomon Hykes, Docker co-founder

Compared to Docker, WebAssembly is 100 times faster at startup, takes up less memory and disk space, and has a better defined security sandbox. However, the downside is that WebAssembly requires its own language SDK and compiler toolchain, making it a more limited developer environment than Docker. WebAssembly is increasingly used in edge computing scenarios where deploying Docker is difficult or where application performance is critical.

One of Docker’s strengths is its rich tool ecosystem. We want to bring docker-like tools to WasmEdge developers. To do this, we created an alternative runner for CrI-o called Runw to load and run WebAssembly bytecode programs as if they were Docker images.

Install WebAssembly Runner in CRI-O

To support WebAssembly in CrI-O, all you need to do is download the RUNw binary distribution and install it into your CrI-O.

because
runwWasmEdge is already included in the binary code and there is no need to install WasmEdge or any other WebAssembly VM separately.

First, make sure you are using Ubuntu 20.04 with LLVM-10 installed. If you are using a different platform, see how to create runw project documentation for your operating system.

sudo apt install -y llvm-10-dev liblld-10-dev

Make sure you have cri-o, Crictl, ContainerNetworking-plugins and Buildah or Docker installed.

Next, download the Runw Binary build

Wget HTTP: / / https://github.com/second-state/runw/releases/download/0.1.0/runw

Now, you can install Runw into CrI-O as an alternative to WebAssembly.

# Get the wasm-pause utility sudo crictl pull docker.io/beststeve/wasm-pause # Install runw into cri-o sudo cp -v runw /usr/lib/cri-o-runc/sbin/runw sudo chmod +x /usr/lib/cri-o-runc/sbin/runw sudo sed -i -e 's@default_runtime = "Runc "@default_runtime = "runw"@' /etc/crio.crio. conf sudo sed i-e 's@pause_image = "k8s.gcr. IO /pause:3.2"@pause_image  = "docker.io/beststeve/wasm-pause"@' /etc/crio/crio.conf sudo sed -i -e 's@pause_command = "/pause"@pause_command = "pause.wasm"@' /etc/crio/crio.conf sudo tee -a /etc/crio/crio.conf.d/01-crio-runc.conf <<EOF [crio.runtime.runtimes.runw] runtime_path = "/usr/lib/cri-o-runc/sbin/runw" runtime_type = "oci" runtime_root = "/run/runw" EOF

Finally, restart crI-O so that the new WebAssembly Runner takes effect.

sudo systemctl restart crio

Build Wasm applications with Rust

The Wasm application in the following case was written by Rust. To make these programs work, make sure you have the Rust and Rustwasmc toolchains installed.

You need the Rust compiler and RustWASMC to build Rust sources into WASM bytecode files. If you already have a WASM bytecode program and just want to run it through with crI-o, you can skip this section.

The application source code is just a main.rs function. At this point. This application demonstrates how to access file system and other operating system resources from WasmEdge using the standard Rust API.

fn main() { println! ("Random number: {}", get_random_i32()); println! ("Random bytes: {:? }", get_random_bytes()); println! ("{}", echo("This is from a main function")); print_env(); create_file("/tmp.txt", "This is in a file"); println! ("File content is {}", read_file("/tmp.txt")); del_file("/tmp.txt"); } pub fn get_random_i32() -> i32 { let x: i32 = random(); return x; } pub fn get_random_bytes() -> Vec<u8> { let mut rng = thread_rng(); let mut arr = [0u8; 128]; rng.fill(&mut arr[..] ); return arr.to_vec(); } pub fn echo(content: &str) -> String { println! ("Printed from wasi: {}", content); return content.to_string(); } pub fn print_env() { println! ("The env vars are as follows."); for (key, value) in env::vars() { println! ("{}: {}", key, value); } println! ("The args are as follows."); for argument in env::args() { println! ("{}", argument); } } pub fn create_file(path: &str, content: &str) { let mut output = File::create(path).unwrap(); output.write_all(content.as_bytes()).unwrap(); } pub fn read_file(path: &str) -> String { let mut f = File::open(path).unwrap(); let mut s = String::new(); match f.read_to_string(&mut s) { Ok(_) => s, Err(e) => e.to_string(), } } pub fn del_file(path: &str) { fs::remove_file(path).expect("Unable to delete"); }

You can build the application into a WASM bytecode file by using the following command line.

rustwasmc build

The WASM bytecode file is here.

Build and publish a Docker Hub image for your Wasm app

You can now publish the entire WASM bytecode file to Docker Hub as if it were a Docker image.

First, create a Dockerfile in the PKG/directory, as shown below.

FROM scratch
ADD wasi_example_main.wasm .
CMD ["wasi_example_main.wasm"]

Create an image and publish it to Docker Hub.

sudo buildah bud -f Dockerfile -t wasm-wasi-example
sudo buildah push wasm-wasi-example docker://registry.example.com/repository:tag

# Example: the following command publishes the wasm image to the public Docker hub under user account "hydai"
sudo buildah push wasm-wasi-example docker://docker.io/hydai/wasm-wasi-example:latest

You can now use Docker tools such as crictl to pull published Wasm files as images. Here is an example of the WASM file image we published.

sudo crictl pull docker.io/hydai/wasm-wasi-example

Use crI-o to start the Wasm app

To get the wasm files up and running, you need to create two configuration files for crI-o. Create a container_wasi.json file, as shown below. It tells the CrI-o runtime where to extract the WASM file image from the Docker repository.

{
  "metadata": {
    "name": "podsandbox1-wasm-wasi"
  },
  "image": {
    "image": "hydai/wasm-wasi-example:latest"
  },
  "args": [
    "wasi_example_main.wasm", "50000000"
  ],
  "working_dir": "/",
  "envs": [],
  "labels": {
    "tier": "backend"
  },
  "annotations": {
    "pod": "podsandbox1"
  },
  "log_path": "",
  "stdin": false,
  "stdin_once": false,
  "tty": false,
  "linux": {
    "resources": {
      "memory_limit_in_bytes": 209715200,
      "cpu_period": 10000,
      "cpu_quota": 20000,
      "cpu_shares": 512,
      "oom_score_adj": 30,
      "cpuset_cpus": "0",
      "cpuset_mems": "0"
    },
    "security_context": {
      "namespace_options": {
        "pid": 1
      },
      "readonly_rootfs": false,
      "capabilities": {
        "add_capabilities": [
          "sys_admin"
        ]
      }
    }
  }
}

Next, create a sandbox_config.json file, as shown below. It defines the sandbox environment in which to run wASM applications.

{ "metadata": { "name": "podsandbox12", "uid": "redhat-test-crio", "namespace": "redhat.test.crio", "attempt": 1}, "hostname" : "crictl_host", "log_directory" : ""," dns_config ": {" searches" : [" 8.8.8.8 "]}, "port_mappings" : [], "resources": { "cpu": { "limits": 3, "requests": 2 }, "memory": { "limits": 50000000, "requests": 2000000 } }, "labels": { "group": "test" }, "annotations": { "owner": "hmeng", "security.alpha.kubernetes.io/seccomp/pod": "unconfined" }, "linux": { "cgroup_parent": "pod_123-456.slice", "security_context": { "namespace_options": { "network": 0, "pid": 1, "ipc": 0 }, "selinux_options": { "user": "system_u", "role": "system_r", "type": "svirt_lxc_net_t", "level": "s0:c4,c5" } } } }

You can now create a Cri-o pod as follows:

Create POD, the output will be different from the example. Sudo crictl runp sandbox_config. Json e75df00cc1cf4bff8bff660718139e3ad973c7180baceb9c84d074b516a4 # 7992 set an instrumental variables for later use. POD_ID=7992e75df00cc1cf4bff8bff660718139e3ad973c7180baceb9c84d074b516a4

From POD, you can create a container to run wASM bytecode programs in isolation.

# Create container instance, the output will be different from the example. sudo crictl create $POD_ID container_wasi.json sandbox_config.json 1d056e4a8a168f0c76af122d42c98510670255b16242e81f8e8bce8bd3a4476f

Finally, start the container and view the output of the WASM application.

# list containers, The status should be 'Created' sudo crictl ps -a CONTAINER IMAGE Created STATE NAME ATTEMPT POD ID 1d056e4A8A168 Hydai /wasm-wasi-example: Latest About a minute ago Created Podsandbox1 - Wasm-wasi 0 7992e75df00cc  1d056e4a8a168f0c76af122d42c98510670255b16242e81f8e8bce8bd3a4476f D056e4a8a168f0c76af122d42c98510670255b16242e81f8e8bce8bd3a4476f # 1 check the container status again. If the container does not complete its work, you will see the health status. # Because this example is small. You might see Exited at this point. sudo crictl ps -a CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID 1d056e4a8a168 hydai/wasm-wasi-example:latest About a Minute ago Running Podsandbox1-wasm-WASi 0 7992e75DF00cc # When the container is complete. You can see the state is Exited. sudo crictl ps -a CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID 1d056e4a8a168 hydai/wasm-wasi-example:latest About a Minute ago Exited Podsandbox1-wasm-wasi 0 7992e75df00cc # View container sudo crictl logs 1 d056e4a8a168f0c76af122d42c98510670255b16242e81f8e8bce8bd3a4476f Test 1: printing a Random number of Random number: 960251471 Test 2: Print Random bytes: [50, 222, 62, 128, 120, 26, 64, 42, 210, 137, 176, 90, 60, 24, 183, 56, 150, 35, 209, 211, 141, 146, 2, 61, 215, 167, 194, 1, 15, 44, 156, 27, 179, 23, 241, 138, 71, 32, 173, 159, 180, 21, 198, 197, 247, 80, 35, 75, 245, 31, 6, 246, 23, 54, 9, 192, 3, 103, 72, 186, 39, 182, 248, 80, 146, 70, 244, 28, 166, 197, 17, 42, 109, 245, 83, 35, 106, 130, 233, 143, 90, 78, 155, 29, 230, 34, 58, 49, 234, 230, 145, 119, 83, 44, 111, 57, 164, 82, 120, 183, 194, 201, 133, 106, 3, 73, 164, 155, 224, 218, 73, 31, 54, 28, 124, 2, 38, 253, 114, 222, 217, 202, 59, 138, 155, 71, 178, 113] Test 3: Echo from wasi: Printed is from a main function This is from a main function Printing environment variable The env vars are as follows. The PATH: / usr/local/sbin, / usr/local/bin: / usr/sbin, / usr/bin: / sbin/bin TERM: xterm HOSTNAME: crictl_host PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin The args are as follows. /var/lib/containers/storage/overlay/006e7cf16e82dc7052994232c436991f429109edea14a8437e74f601b5ee1e83/merged/wasi_example _main.wasm 50000000 Test 5: Create file '/ TMP. TXT' containing 'This is in a file' Test 6: File Content is This is in a File Test 7: Delete the previous File

The next step

In this article, we saw how to start, run, and manage the WasmEdge application using a Docker-like cri-O tool.

The next step is to use Kubernetes to manage the WasmEdge container. To do this, you need to install a Runner binary in Kubernetes so that it can support both regular Docker images and WASM bytecode images.