WASM, Containers? What?

WASM, Containers? What?

October 1, 2025

TL;DR

Understanding WASM and how it relates with Containers.

+++ WASM + PWA as your FFMPEG video editor +++ Practical WASM with VERT to convert files

Keep reading if you like portability and serverless/edge computing.

Intro

Context for WASM, in case you have been doing CSR projects recently, like I’ve been:

In a regular Client-Side Rendering (CSR) setup, the JavaScript code is executed in the client’s browser, and this process involves an overhead that makes it slower than compiled languages.

Here’s the breakdown of why it takes more time:

  • Downloading the Code: The browser first has to download the entire JS bundle. For large applications, this can be a big file, which adds to the initial load time.

  • Parsing and Interpretation: Once downloaded, the browser’s JavaScript engine must parse and interpret the code. It reads the text-based code, translates it into an intermediate format called bytecode, and then executes it line by line.

  • Just-in-Time (JIT) Compilation: To improve performance, modern engines use a JIT compiler. The engine monitors the running code and identifies “hot spots” (frequently executed sections). It then compiles only those small parts of the bytecode into optimized machine code. This is an on-the-fly process that adds to the initial execution time as the engine decides what to optimize.

This entire process—from download to parsing and JIT compilation—happens on the user’s machine, adding latency to the initial page load.

A pre-compiled language like WASM skips most of these steps.

The browser can simply download the already-compiled binary .wasm file and execute it directly, leading to faster startup and better performance for computationally intensive tasks.

What about Web Assembly?

With WASM we can run Apps coded in other language (other than web language like js) in our browsers.

WASM allow us to compile code and run it in various environments, like browsers.

Regardless of OS and even architecture ARM/X86/RISC-V…

With Docker we have (generally) bigger Images than WASM.

Wasm follows both OCI and w3c standards.

graph TD;
    WASM_Module_1(".WASM Module 1,2,3...") -->|WA| WASM_Runtime("WASM Runtime (wasmtime, wamr, wagi)");
    WASM_Runtime -->|WASI - Web Assembly Interface| Host_OS("Host OS");

Thanks to DevOps Toolkit

WebAssembly (WASM) is not a programming language in the way that C or JavaScript are.

It’s a compilation target, a low-level binary format that a browser’s WASM engine can execute.

Think of it as a form of assembly code, but for a virtual machine rather than a specific physical processor.

WASM is very similar to C in concept because C is often used as the source language for code that gets compiled down to WASM.

WASM vs C

WASM and C are not interchangeable, but they have a strong, symbiotic relationship.

  • C is a high-level programming language you write to be read by humans. It has a well-defined syntax and is used to express logic.
  • WASM is a low-level binary format meant to be executed by a machine. It’s not designed for humans to write by hand (though it has a text format for debugging).

How they relate: You write your performance-critical code in a language like C (or Rust, C++, etc.). Then, you use a special compiler (like Emscripten for C/C++) to translate that C code into a .wasm file. This .wasm file is what the browser actually loads and runs.

The reason they are so compatible is that C is a low-level language that gives the programmer direct control over memory, which is exactly what WASM is designed for.

This makes C an ideal language for targeting WASM.

Getting Started with WASM

Get Started with WASM 🐰

Install emcc:

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest

./emsdk activate latest
source ./emsdk_env.sh

This compiles the C to —> html, js, wasm (this is our WASM Module):

#emcc helloworld.c -o helloworld.html
emcc -o hello.html hello.c

See what was created:

python3 -m http.server 8080 #choose any port

To run wasm inside docker: you need to enable it as Beta feature at this time of writing

sudo apt-get install ./docker-desktop-4.27.2-amd64.deb
#settings -> features in development -> Enable WASM

Now instead of compiling the html or js app, we will just compile the .wasm module:

emcc -o hello.wasm hello.c

#ll hello.wasm
#file hello.wasm

Create your Dockerfile for Wasm:

FROM scratch

COPY helloworld.wasm /helloworld.wasm
ENTRYPOINT [ "/helloworld.wasm" ]

Build your WASM Image:

docker buildx build --platform wasi/wasm -t fossengineer/helloworld-wasm -f DockerfileWasm .
#docker image ls | head

Run WASM with Docker:

docker run --platform wasi/wasm --runtime io.containerd.wasmedge.v1 fossengineer/helloworld-wasm

Run an already created WASM (as standalone) with docker:

docker run --rm --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm secondstate/rust-example-hello:latest

WASM and PWA

WebAssembly (WASM) and Progressive Web Apps (PWAs) can be combined, and doing so is a powerful way to create modern, high-performance web applications.

They complement each other perfectly because they solve different problems.

How They Work Together

  • PWA’s Role: The PWA part handles the native-like app experience. It manages offline functionality, provides push notifications, and allows the application to be installed on a user’s device. This gives the user an app icon and a dedicated window, making the website feel like a regular application.

  • WASM’s Role: The WASM part handles the heavy lifting and computational tasks. It provides a way to run high-performance code, written in languages like C++ or Rust, with near-native speeds. This is used for tasks that would be slow or inefficient if done with JavaScript.

The synergy is what makes this combination so effective.

For example, a video editing PWA could use its service worker to cache the application so the user can open it offline (PWA functionality).

When the user wants to apply a complex filter, the application uses a WASM module to perform the intensive video processing quickly and efficiently in the browser (WASM functionality).

This provides a seamless, fast experience that was once only possible with a native desktop app.

You could create a PWA that does video processing using FFmpeg with WebAssembly.

This is a very popular and powerful use case for WASM.

In fact, see: https://github.com/anhostfr/compress.lol, which I forked here

Compress videos in your browser to fit Discord limitations and more

Note: Compression happens entirely in your browser. No files are uploaded to any server.

How It Works

This setup leverages the strengths of both technologies:

  1. FFmpeg to WASM: The core of this process involves compiling the powerful and well-established FFmpeg library from its original C code into a WASM module. This makes the video processing logic available to run directly inside a web browser.

  2. PWA Functionality: The PWA part gives your web application a native feel. You’d use a service worker to make the app work offline and a manifest file to allow users to install it on their home screen. The user interface (HTML, CSS, JavaScript) handles the front-end, like file selection and progress indicators.

  3. The Video Processing Flow:

    • A user visits your PWA and selects a video file.
    • The JavaScript in the app uses the File API to read the video.
    • The app then loads the FFmpeg WASM module.
    • The JavaScript passes the video data to the WASM module along with the desired commands (e.g., “convert to MP4,” “resize video,” or “add a filter”).
    • The WASM module, running in the browser’s memory, processes the video. This is the computationally expensive part, which is handled efficiently by WASM.
    • Once the processing is complete, the WASM module returns the output video data to the JavaScript, which then lets the user download the result.

This approach is highly beneficial because the heavy processing is done on the user’s device, not your server.

This means you don’t have to pay for server processing time or bandwidth for every video conversion.


Conclusions

This pelado nerd video is a good starting point for WASM:

Questions Given an image, could this kind of calculations https://github.com/jlleongarcia/X-ray-imaging-analysis/tree/main be done with CSR or WASM?

choco install make
#make version

Yes, WebAssembly (Wasm) aims to make browsers a runtime environment not just for JavaScript but for many programming languages.

WebAssembly is designed as a portable, low-level bytecode format that can serve as a compilation target for languages like C, C++, Rust, and others, enabling them to run at near-native speed inside web browsers.

It complements JavaScript and is meant to overcome JavaScript’s performance limitations in high-demand applications, such as 3D games and virtual/augmented reality.

The WebAssembly standard is also intended to be platform-independent and open, supporting execution outside browsers as well, paving the way for a universal runtime beyond just web usage.

This means browsers will be able to execute code compiled from diverse languages through a common runtime that includes sandboxing and security features, effectively making browsers a multi-language runtime environment alongside JavaScript.

In summary, WebAssembly’s goal is to extend browser runtime capabilities to languages beyond JavaScript, creating a fast, secure, and portable execution environment for various languages compiled to Wasm.

Practical WASM - VERT

VERT is a file conversion utility that uses WebAssembly to convert files on your device instead of a cloud.

Check out the live instance at vert.sh.

The next-generation file converter. Open source, fully local* and free forever.

VERT is built in Svelte and TypeScript.

You can try vert at: https://vert.sh

This can even convert video (but not in the browser) with FFMPEG and RUST: https://github.com/VERT-sh/VERT/blob/main/docs/VIDEO_CONVERSION.md

Why FFMPEG and RUST? 🚀

Running FFmpeg with Rust bindings offers advantages mainly in safety and application integration but does not replace the default way FFmpeg is run, which is as a native C/C++ binary or through its CLI.

  • FFmpeg, by default, is written in C/C++ and runs as a command-line application (CLI) or through its C API for direct integration in software projects.[1][2]
  • Most users interact with it via terminal commands, scripts, or through external programs that call the binary.[2]

Advantages of Rust Integration

  • Rust bindings (or libraries like rsmpeg or ez-ffmpeg) allow developers to harness FFmpeg’s power in Rust applications while leveraging Rust’s robust memory safety and error handling.[3][4][5]
  • Using Rust wrappers can help prevent memory leaks and common security issues inherent to directly using FFmpeg’s C API, making your multimedia processing code more secure and reliable.[4][5]
  • Rust abstractions can make multimedia tasks easier and more ergonomic compared to composing complex raw FFmpeg CLI commands, improving developer productivity and application stability.[5][3][4]

When to Use Which

  • For most end-users and scripting tasks, calling the regular FFmpeg binary is fastest and simplest.
  • For developers building complex or safety-critical applications, integrating FFmpeg with Rust provides extra benefits in safety, maintainability, and native performance, while preserving nearly all of FFmpeg’s rich feature set.[3][4][5]

In summary, FFmpeg runs by default as a C/C++ CLI tool, but using it in Rust brings safety, easier integration, and cleaner code for application development without losing core functionality.[4][5][3]

5


FAQ

Interpreted vs Compiled Languages

Neither JavaScript nor Python are traditional compiled languages.

They are primarily interpreted, but modern engines use Just-in-Time (JIT) compilers to gain some of the benefits of compiled languages.

The main difference between these two categories is when the code is translated into machine-readable instructions.

  • Compiled Languages 📝➡️💻: The source code is translated into machine code before the program is run. A separate program called a compiler reads the entire source code file and converts it into a binary file (an executable or .exe). You then run this binary file directly. Examples: C, C++, Go, Rust.

  • Interpreted Languages 📝➡️…➡️💻: The source code is translated and executed line by line at runtime by an interpreter. There is no separate pre-compilation step. When you run a script, the interpreter reads the first line, executes it, then moves to the next, and so on. Examples: Python, Ruby.

JavaScript and Python are considered interpreted, but modern implementations blur the lines.

When you run a Python script or a JavaScript file, the interpreter first compiles the code into a format called bytecode.

This bytecode is then executed by a virtual machine.

However, to speed things up, modern JavaScript engines (like Google’s V8) and Python implementations (like PyPy) use a Just-in-Time (JIT) compiler.

This hybrid approach is why you might hear that JavaScript is both interpreted and compiled.

Compiled Languages

  • Pros:
    • High Performance 🚀: Since the entire code is converted to optimized machine code ahead of time, compiled programs run much faster and more efficiently. This is critical for applications like video games, operating systems, and scientific simulations.
    • Early Error Detection 🐛: The compiler checks for many errors (like type mismatches) before the program even runs, making the final code more robust and reliable.
  • Cons:
    • Slower Development Cycle ⏳: The compilation step can take a long time, especially in large projects. Every time you make a small change, you have to recompile the entire program.
    • Platform-Dependent 🌐: The compiled binary file is specific to the CPU and operating system it was compiled for (e.g., a Windows .exe won’t run on macOS).

Interpreted Languages

  • Pros:
    • Faster Development Cycle 🏃: You can run code immediately after writing it without a compilation step, which speeds up testing and prototyping.
    • Platform-Independent 🌍: The same source code can be run on any system that has the right interpreter installed.
  • Cons:
    • Slower Performance 🐢: Without the optimizations of a full compiler, interpreted code generally runs slower than compiled code. Each line must be translated at runtime, which introduces overhead.
    • Runtime Errors 💥: Errors might not be found until the code is actually executed, which can be more difficult to debug.

Hosting for WASM

As WASM is something that we compile and ser to clients to execute, you can use any static hosting alternative.

What to run with WASM

Computationally expensive tasks are those that require a lot of processing power (CPU/GPU cycles) and time to complete.

They often involve complex calculations, large datasets, or intricate simulations.

In the context of web applications, here are some common examples of such tasks:

1. Media Processing

  • Image and Video Editing: Think of tasks like applying filters, resizing high-resolution images, transcoding video formats, or rendering complex animations. These operations require manipulating millions of pixels and data points.
  • Audio Processing: Tasks such as real-time audio effects, mixing multiple tracks, or encoding/decoding large audio files.

2. Scientific and Engineering Simulations

  • Data Visualization: Creating complex 3D graphs, plotting large scientific datasets, or rendering intricate models (e.g., CAD designs) on the fly. This often involves thousands of mathematical operations to represent the data visually.
  • Scientific Computations: Running simulations for fields like physics, fluid dynamics, or financial modeling. These algorithms often involve many iterative calculations.

3. Machine Learning and AI

  • Inference: Running a pre-trained machine learning model directly in the browser to make predictions. This is common for things like a real-time face recognition tool, a text-to-speech converter, or a simple AI-powered image generator.
  • Training Models: While full model training is usually done on a server, some smaller models can be trained on the client side, which is very computationally expensive.

4. Gaming

  • Physics Engines: Simulating realistic physics for in-browser games, including collision detection and particle effects. These tasks require constant, rapid calculations to keep the game running smoothly.
  • 3D Rendering: Drawing complex 3D environments, characters, and objects with realistic lighting and textures. This is a very CPU- or GPU-intensive task that a browser’s JavaScript engine would struggle with.

WASM vs Containers

That’s an excellent question, as WASM and containers (like Docker and Podman) are both technologies for running applications, but they do it in fundamentally different ways.

They aren’t mutually exclusive.

Instead, they represent two distinct approaches to achieving similar goals: portability, security, and isolation.

  • Containers are like shipping containers. 📦 They bundle an application with everything it needs to run—the code, libraries, and even the entire operating system environment—into a single, isolated package. This package is then shipped to a server where it runs on top of the host machine’s Linux kernel.
  • WASM is like a digital machine code for a universal virtual CPU. 💻 It’s a low-level format that is executed by a lightweight virtual machine. It doesn’t need a full operating system; it only needs a small runtime that understands the WASM format.
FeatureContainers (e.g., Docker)WASM
Isolation ModelProcess-level isolation via the host OS kernel (namespaces, cgroups).Sandboxed environment within a lightweight virtual machine.
DependenciesBundles the application’s code and its dependencies, including the operating system’s libraries.Bundles only the application’s code and a tiny runtime.
SizeCan be hundreds of megabytes or even gigabytes.Typically a few kilobytes to a few megabytes.
Target HostRequires a Linux kernel.Can run on any system with a WASM runtime, including a web browser or a server.
Use CaseIdeal for running traditional server applications, databases, and microservices.Ideal for running lightweight, single-purpose functions and applications, especially in the browser.

The Relationship: Not Competitors, but even Complements

WASM is often seen as an alternative to containers for certain use cases, particularly for serverless computing and edge computing.

Instead of spinning up a full container for a simple function, a platform could just run a tiny, fast WASM module.

This saves on memory and startup time.

However, they can also work together: You can run a WASM runtime inside a container.

This allows you to combine the security and isolation of a container with the portability and lightweight nature of WASM.

The container provides a standardized environment to deploy your WASM application, while WASM ensures the application itself is small and fast.

This is a common pattern in the cloud where performance and resource efficiency are critical.

It needs: Run Time (wasmtime, wamr, wagi…) and an interface (WASI - webassembly system interface ).

WASI will make sure to run our binary in any architechture and Operative System.

Example -> Package your C code in any other language, like inside JS.

https://www.youtube.com/watch?v=bgWTf3m6HG0


Welcome to the World of WebAssembly

Explore the fascinating world of WebAssembly (WASM), where languages like C++, Rust, Python, and more can be used to build software that runs in web browsers with near-native performance. This quick guide will help you understand the basics of WebAssembly, its potential, and how it could revolutionize web software development.

What is WebAssembly? 🤔

  • Definition: WebAssembly, or WASM, is a low-level language similar to assembly. It can be written as text or converted to a binary format that runs on all modern browsers.
  • Purpose: WASM is designed not to replace JavaScript but to work alongside it, providing a compilation target for applications written in traditional non-web languages, enabling high-performance directly in the browser.

Building WebAssembly Apps 🛠️

  • Tools:
    • MScripten: Converts C or C++ programs to WASM.
    • Assembly Script: Similar to TypeScript, it compiles to WASM. Projects can be started with Node.js and npm, with your first module written in index.ts.

Key Features of WebAssembly 🔑

  • Static and Compiled: WASM is a static, compiled language with strict type guarantees.
  • Type Safety: It requires specifying types like 32-bit integers or 64-bit floating points and uses maps with strongly typed key-value pairs.
  • Executable: Code is compiled down to a .wasm binary file that can be run in the browser using the WebAssembly API.

Key Takeaways ✨

  • Performance: WebAssembly allows for building high-performance applications for the web.
  • Complementary to JavaScript: Enhances rather than replaces JavaScript.
  • Rich Tooling: There are many tools and languages for building WebAssembly apps, including Assembly Script and MScripten.
  • Strict Typing: Its static nature and strict type guarantees make it suitable for performance-critical applications.

Leverage WebAssembly in your projects to push the boundaries of what’s possible on the web.


WASM for Python Devs: A Practical Guide

WebAssembly (Wasm) is revolutionizing the way we think about web development, allowing code written in languages like Python to run in the browser at near-native speed. This guide will walk you through the basics of using Python with WebAssembly, from setup to deployment.

  • 📘 Understand WebAssembly Fundamentals

    • Review Basics: Refresh on WebAssembly’s core concepts and capabilities as previously outlined.
  • 🐍 Choose a Python Implementation Select the Python implementation that best fits your project needs:

    • Pyodide: A complete Python environment for the browser, leveraging WebAssembly.
    • PyWasm: A Python library designed to work with WebAssembly modules.
    • Transcrypt: Transpiles Python code to JavaScript, supporting WebAssembly as a compilation target.
    • Emscripten with Python: Compiles Python code to WebAssembly using the Emscripten toolchain.
Tell me more about those Frameworks 👇

Choosing the right Python implementation for your WebAssembly project depends on factors such as your specific use case, performance requirements, ease of use, and compatibility with existing Python codebases

  1. Pyodide:

    • Use Case: Pyodide is ideal for situations where you need a full Python runtime environment in the browser. It includes the Python interpreter, standard library, and many popular Python packages compiled to WebAssembly.
    • Performance: Since Pyodide runs Python code in the browser, its performance may not match that of native Python or highly optimized WebAssembly code. However, it offers a convenient way to execute Python code directly in web applications.
    • Compatibility: Pyodide aims to be compatible with CPython, the reference implementation of Python, which ensures compatibility with a wide range of existing Python codebases.
    • Ease of Use: Pyodide provides a straightforward way to integrate Python into web applications without requiring complex setup or toolchains.
  2. PyWasm:

    • Use Case: PyWasm is suitable for scenarios where you want more control over the compilation process and direct interaction with WebAssembly modules from Python code.
    • Performance: By compiling Python code to WebAssembly directly, PyWasm can potentially achieve better performance compared to running Python in the browser. However, the performance gains may vary depending on the complexity of the code and optimization techniques used.
    • Compatibility: PyWasm may have limitations in terms of compatibility with Python’s standard library and third-party packages compared to Pyodide. It’s important to ensure that your Python code is compatible with PyWasm’s restrictions and limitations.
    • Ease of Use: PyWasm may require more effort to set up and integrate compared to Pyodide, as it involves manually compiling Python code to WebAssembly and managing the interaction between Python and WebAssembly modules.
  3. Transcrypt:

    • Use Case: Transcrypt is suitable for projects where you want to write Python code that can be transpiled to JavaScript or WebAssembly for execution in the browser.
    • Performance: Transcrypt allows you to leverage the performance benefits of WebAssembly by targeting it as a compilation target. However, the performance may not be as optimized as writing code directly in WebAssembly.
    • Compatibility: Transcrypt aims to be compatible with a subset of Python syntax and standard library features. While it supports many Python language features, some advanced features may not be fully supported.
    • Ease of Use: Transcrypt simplifies the process of integrating Python code into web applications by providing a familiar Python syntax and allowing you to target multiple compilation targets, including WebAssembly.
  4. Emscripten with Python:

    • Use Case: Emscripten can be used to compile Python code to WebAssembly, similar to how it’s used for compiling C/C++ code. This approach provides fine-grained control over the compilation process and optimizations.
    • Performance: Emscripten can produce highly optimized WebAssembly code, potentially achieving performance comparable to or better than native code. However, the compilation process may be more involved and require expertise in Emscripten’s toolchain.
    • Compatibility: Compatibility with existing Python codebases may vary, and certain Python features or libraries may not be fully supported or may require additional configuration.
    • Ease of Use: Using Emscripten with Python may require more expertise in the Emscripten toolchain and configuration compared to other options. It’s suitable for projects where performance optimization and control over the compilation process are priorities.

In summary, the choice between Pyodide, PyWasm, Transcrypt, or Emscripten with Python depends on your specific requirements, familiarity with the tools and technologies involved, and the trade-offs between ease of use, performance, and compatibility with existing Python codebases.

  • 🔧 Set Up Your Development Environment

    • Install Tools: Get the necessary tools and libraries for your chosen Python implementation.
    • Configure IDE: Set up your text editor or integrated development environment (IDE) for Python development.
  • ✏️ Write Python Code

    • Develop: Begin crafting Python code for your application or module.
    • Compatibility: Ensure compatibility with the Python implementation you have selected.
  • *🛠 Compile Python to WebAssembly

    • Compilation Process:
    • For Pyodide, Transcrypt, or Emscripten with Python: Follow respective guides to compile your Python code to WebAssembly.
    • For PyWasm: Learn to load and execute WebAssembly modules created from Python code.
  • 🚀 Optimize Performance

    • Enhance Code: Optimize your Python code to boost performance prior to compiling to WebAssembly.
    • Experiment: Test various optimization strategies and evaluate their performance impacts.
  • 🤝 Integration with JavaScript

    • Interactivity: Learn to handle interactions between Python code running in WebAssembly and JavaScript.
    • Data Exchange: Master techniques for passing data between JavaScript and Python.
  • 🧪 Testing and Debugging

    • Testing: Ensure your Python code behaves as expected when running within WebAssembly.
    • Debugging: Utilize browser developer tools and other methods to troubleshoot issues.
  • 🌐 Deployment

    • Packaging: Prepare your Python code, compiled to WebAssembly, for deployment.
    • Hosting: Serve your WebAssembly modules alongside your web application.
  • 🏗 Build a Project

    • Practical Application: Use your knowledge to create a project that integrates Python with WebAssembly.
    • Scale Complexity: Start small and gradually expand the complexity of your projects.
  • 🔍 Explore Advanced Topics (Optional)

    • Deep Dive: Delve into advanced topics like optimizing Python for WebAssembly, exploring multi-threading, or integrating with comprehensive Python libraries and frameworks.

For a first contact with integrating Python with WebAssembly, I would recommend starting with Pyodide. Here’s why:

  • Ease of Use: Pyodide provides a straightforward way to run Python code in the browser without the need for complex setup or compilation processes. You can simply include the Pyodide library in your web application, and you’re ready to execute Python code directly in the browser environment.

  • Compatibility: Pyodide aims to be compatible with CPython, the reference implementation of Python, which means it supports a wide range of Python language features and standard library modules. This compatibility makes it easier to port existing Python code or leverage existing Python libraries in your web applications.

  • Rich Ecosystem: Pyodide includes a significant portion of the Python standard library and supports many popular third-party packages. This allows you to access a rich ecosystem of Python tools and libraries directly in the browser environment, enhancing the capabilities of your web applications.

  • Immediate Feedback: With Pyodide, you can interactively execute Python code in the browser environment, which provides immediate feedback and facilitates rapid prototyping and experimentation. This interactive workflow can be beneficial for learning and exploring Python’s capabilities in the context of web development.


Running WASM inside Docker

you can run your wasm modules inside a docker contsiner

FROM SCRATCH