This post gives an overview of how to build applications using the updated Docker + WASM technical preview, along with some observability best practices.
WebAssembly, also known as WASM, serves as a binary instruction format for a stack-based virtual machine. This means it is a new type of code and is specifically designed to run in modern web browsers. This is made possible because WASM is architected as a portable compilation target for programming languages. This design enables deployment on the web for any type of client and server applications.
In principle, WASM is a low-level language, but it is designed to be easy to compile to from other languages. Therefore, an application developer can write programs in languages such as C, C++, Rust, etc. and compile them into a WASM target to be run in the browser.
The ultimate goal of WASM is to help application developers package and deploy their apps for deployment. Where have we heard this before – with Docker and containers. Since there is a large overlap between the aims of WASM and Docker, it is a natural choice for them to work together. Enter, Docker + WASM technical preview. Announced in October 2022, Docker could be used to package, deploy, and manage WASM applications, just like any other type of containerized application. Fast forward six months, the team announced a refreshed integration. Let us take a look at some of the details about this effort.
The WASM+Docker Technical Preview project was started to explore the potential of running WebAssembly (WASM) applications inside Docker containers. WASM and Docker, both of which are aimed squarely at broadening the horizons for application developers, share some underpinnings which makes their integration very valuable. The WASM+Docker Technical Preview project combines the benefits of WASM and Docker to create a powerful platform for modernized web applications. The salient features promised to developers are three-fold:
To quote Jake Levirne, Head of Product at Docker — “Wasm is complementary to Docker — in whatever way developers choose to architect and implement parts of their application, Docker will be there to support their development experience”.
A second iteration of WASM+Docker was announced in March 2023. The features released in this iteration made it easier for developers to write, debug, configure, and maintain WASM apps, especially running as containerized workloads using Docker. The most significant update was the support made available for new WASM runtimes.
A WebAssembly (WASM) runtime is a software environment that executes WASM code. It provides the necessary infrastructure for loading, compiling, and running WASM modules. WASM runtimes are typically implemented as libraries or executables that can be embedded in other applications. They can also be used as standalone tools for running WASM modules. There are a number of different WASM runtimes available, each with its own specific traits. Some of the most popular ones are:
There are several use cases for a technology like WASM because of its broad range of applications. Here are some use cases that best illustrate the need for the technology:
There are a few recurring themes around WASM that make it popular among web application developers today. The first is the promise of increased performance. Who doesn’t appreciate fast and responsive applications? The ability to design performant web applications using a broad swathe of programming languages is an enticing prospect for potential WASM users. In comparison to Linux containers, WASM applications consume less resources. This is a result of the design where code is compiled as WASM binaries that require far less resources than comparable linux binaries. Also, WASM applications are limited to being single-threaded compared to equivalent multi-threaded applications running on linux, resulting in far less CPU usage. Due to their ability to run in sandboxed environments, WASM is a good choice for security requirements. These are the chief reasons why WASM is rising in popularity among developers.
All that being said, WASM isn’t perfect, and the Docker + WASM Technical preview is in an early stage. There are several things to keep in mind when trying the Docker + WASM technical preview. The common issues that people are encountering are:
Now that we’ve seen what is good and what’s not good about the WASM + Docker Technical preview, let’s get into a quick tutorial to see where to begin. This tutorial is written for a TypeScript application. As with any new technology, there are a few prerequisites for this one too. They are:
Outline for the tutorial:
Let’s take a look at these steps in detail:
First, create a new TypeScript project
mkdir ts-wasm-example
cd ts-wasm-example
vi app.ts
Then save the following into the `app.ts` file, hit `i` to insert into the file and paste the following:
const sayHello = () => {
console.log("Hello, world!");
};
export { sayHello };
Tip: To save and close the newly created file press escape if still in insert mode, then press `:wq`
Build the TypeScript application into a WASM module
tsc
This will create a ts-wasm-example.wasm file in the current directory. Next, write a Dockerfile which will build an image using this Dockerfile. It will create an extremely minimal container containing only the “my-wasm-app.wasm” file. When the container is run, it will automatically execute the Wasm application as its main process.
The “scratch” image is a special minimalistic empty image that is often used as a starting point for creating small, self-contained containers. The command in the next line copies the file named “my-wasm-app.wasm” from the build context (the directory where the Dockerfile is located) into the root directory of the container. Then, the CMD command in the third line sets the default command to run the “my-wasm-app.wasm” file, which is the WebAssembly application copied in the previous step.
FROM scratch
COPY my-wasm-app.wasm /
CMD ["/my-wasm-app.wasm"]
Next, build the Docker image.
docker build -t my-wasm-app .
Once built successfully, run the image.
docker run my-wasm-app
This will start a Docker container that will run the WASM module. You should see the following output in the console:
Hello, world!
Going through these steps will help you verify that a basic setup is available for working with the Docker _ WASM Technical Preview.
Next, we will see how to add observability capabilities to this application. First, install the npm packages corresponding to the opentelemetry capabilities.
npm install @opentelemetry/api @opentelemetry/tracing @opentelemetry/metrics
Open the TypeScript app created in the preview step and modify it to include the OpenTelemetry provider.
Tip: To use vim again simply `vi app.ts` then `gg` followed by `V` and `G` to select all in the file before pasting the below.
import {
OpenTelemetry,
Metrics,
MetricsProvider,
TelemetryClient,
} from "@opentelemetry/api";
import { TracerProvider } from "@opentelemetry/tracing";
const ot = new OpenTelemetry();
const metrics = new Metrics(ot);
const metricsProvider = new MetricsProvider(metrics);
const tracerProvider = new TracerProvider();
const client = new TelemetryClient(tracerProvider, metricsProvider);
client.start();
const sayHello = () => {
console.log("Hello, world!");
};
export { sayHello };
client.stop();
This code will create a new OpenTelemetry instance and initialize the metrics and tracing providers. It will then create a new TelemetryClient and start it. Finally, it will do some work that you want to instrument. When the work is done, the TelemetryClient will be stopped.
Once the file has been modified, go through the steps of building and running the container once again.
docker build -t my-wasm-app .
docker run my-wasm-app
This will now let you collect metrics from the app using OpenTelemetry.
This article should provide an understanding of Docker + WASM Technical Preview. Please remember to use the latest version of Docker Desktop. The Docker + WASM Technical Preview is constantly being updated, so it is important to ensure that the recommended version of Docker is being run. This will help to ensure that you have the latest bug fixes and security updates. Another thing to remember is that before deploying WASM applications to production, test them thoroughly. This will help identify any potential problems and ensure that the applications are compatible with Docker + WASM.
You can also apply the same principles for various programming languages and observability tools. You could integrate Lumigo for getting metrics and traces from your applications when using the Docker + WASM technical preview.