Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Unlock WebAssembly workloads with Podman on macOS and Windows

December 6, 2023
Florent Benoit
Related topics:
ContainersLinux
Related products:
Red Hat Enterprise Linux

    You might have heard excitement recently about WebAssembly (Wasm) and the WebAssembly System Interface (WASI). Imagine a world where you can effortlessly run Wasm binaries and distribute them using Open Container Initiative (OCI) container images—a singular image deployable across multiple architectures.

    Though the concept seems straightforward, accomplishing this task has proven to be quite challenging, particularly on macOS and Windows. The complexity comes from the additional virtual machine running Linux. This machine needs all of the dependencies and prerequisites correctly setup.

    The wait is over. This article unveils the solution, guiding you through the process of enabling Wasm workloads on both macOS and Windows.

    What is WebAssembly ?​

    WebAssembly was designed as a portable compilation target for programming languages, improving performance and portability of web applications (including gaming/emulators). Using a low-level binary format instead of JavaScript boosts applications to have near-native performance.

    The binary format serves as a compilation target and it allows to use a wider range of programming languages such as C, C++, and Rust. While it was a browser/client technology, now it is evolving beyond the web—for example, being adapted for use as a back-end or edge technology (this is what happened to Java, which was first designed for the client side before landing to the server side).

    The Wasm binary format was designed to be secure. Wasm modules are isolated from the rest of the system, and they cannot access any system resources without explicit permission. This makes Wasm modules very safe to run, even in untrusted environments. But on another hand, for developing back-end applications, this restriction is limiting the usage of Wasm.

    The extension of WebAssembly​

    WebAssembly System Interface (WASI) was born as an essential complement to WebAssembly.

    It is a system interface that extends WebAssembly's capabilities beyond the browser, making it suitable for a wider range of environments, including servers, edge devices, and more.

    While with Wasm you had limited access to the host resources, WASI provides a standard set of system calls, enabling WebAssembly modules to interact with the host operating system in a secure and consistent manner: it includes filesystem access, sockets, and other low-level resources.

    Running WebAssembly outside the browser​

    Wasm has shipped in the major browser engines so the usage of Wasm is possible without any third-party addition in the browser land. But when it comes to the edge/system usage, you need to find a virtual machine to run these workloads supporting WASI extension. And there is not only one application to run them, there are several Wasm runtimes such as WasmEdge, Wasmtime, Wasmer, and so on. All runtimes support different CPU architectures.

    Since WASI is still maturing some of the API provided in these runtimes has not reached the standard, so users need to be careful to write portable applications that do not depend on a given runtime.

    Besides running Wasm/WASI workloads on your computer, there is also the question of how you package this binary format, share, and distribute it. A convenient way to distribute and run these workloads is to use OCI images as it provides all the basics: package, storage and distribution of the binaries. Then comes the execution part.

    Using Podman engine with Wasm​

    When using containers with Podman on macOS or Windows, you have a virtual machine called a Podman machine that is executing a Linux environment. We need to add support for Wasm inside this Linux environment. Podman is using the crun project as its OCI runtime, so crun needs to be able to run or delegate execution to Wasm runtimes. Lucky for us, crun supports Wasm execution.

    From the user's point of view, support for Wasm is provided as an additional platform. So when executing a Wasm workload, we specify as a platform --platform=wasi/wasm instead of --platform=linux/arm64 or --platform=linux/amd64, for example.

    Running Wasm workloads with Podman​

    Windows setup

    On Windows, ensure that your Podman machine is a recent one. You can check using the podman version command.

    Depending on the output of the command, you might have extra steps to do:

    • Client's version and server's side version >= v4.7.0: Nothing to do, Wasm support is already there using the wasmedge runtime by default.
    • Client's version >= 4.6.0 but server's side version < 4.7: You need to create a new Podman machine using the command podman machine init --now wasm.
    • Old client/old server (< 4.7.0) or Podman not being installed: follow the getting started at podman.io.

    macOS setup

    On macOS, the support of Wasm runtime is included by default in recent podman machines. The Podman machine on macOS is using Fedora CoreOS and crun/Wasm integration is available since v39.20231119.2.0. You may need to recreate the machine if it's an old one.

    Option 1: Create a compliant machine first by running podman machine init command.

    • Here is the command to create and start a new Podman machine including Wasm:

      podman machine init --cpus 2 --memory 2048 --now
      

      You can use another machine by adding a parameter (machine name) at the end of the command line:

      podman machine init --cpus 2 --memory 2048 --now wasm
      

    Option 2: Install dependencies in the current Fedora CoreOS machine.

    • It's also possible to connect to the Podman machine with the podman machine ssh command and then install the Wasm runtime using:

      sudo rpm-ostree install crun-wasm wasmedge-rt

    Running Wasm images​

    Let's try with a simple Hello World sample.

    We will use an example coming from https://github.com/redhat-developer/podman-desktop-demo/tree/main/wasm/rust-hello-world.

    There is already an OCI image on quay.io. To run the workload, we will use the following command:

    podman run --platform wasi/wasm quay.io/podman-desktop-demo/wasm-rust-hello-world
    

    When running the command, you will see a Podman Hello World that was compiled with a Rust project using the println function and compiled into Wasm using --target wasm32-wasi parameter at compilation time.

    !... Hello Podman Wasm World ...!
    
             .--"--.
           / -     - \
          / (O)   (O) \
       ~~~| -=(,Y,)=- |
        .---. /`  \   |~~
     ~/  o  o \~~~~.----. ~~
      | =(X)= |~  / (O (O) \
       ~~~~~~~  ~| =(Y_)=-  |
      ~~~~    ~~~|   U      |~~
    
    Project:   https://github.com/containers/podman
    Website:   https://podman.io
    Documents: https://docs.podman.io
    Twitter:   @Podman_io

    you can omit the --platform wasi/wasm flag but in that case you'll get a warning that the platform of the image is not matching the platform of your computer (WARNING: image platform (wasi/wasm) does not match the expected platform (linux/arm64))

    From this point, you can run other OCI images using Wasm workloads, not only the Podman Hello World sample.

    Note: if you don't have the prerequisites installed in your Podman machine, you will see this error: 

    Error: requested OCI runtime crun-wasm is not available: invalid argument

    In that case, you should check that the prerequisites from the previous section are met.

    Building Wasm OCI images with Podman​

    Building with a specific platform/architecture​

    Running Wasm workload is an interesting use case from a consumer point of view. It helps to consume Wasm binaries. But another interesting case is to distribute and build these Wasm images so anyone could run them quickly.

    The goal is to have a minimal image containing only the Wasm binary. For that we will use a multi-stage build. First stage will be the platform to build/compile the .wasm binary file and the second/last stage will copy the binary to a scratch image.

    When building images it will use the architecture of the host operating system by default. If you are using a Mac computer with ARM chip, then the Linux images will default to linux/arm64. Using a Mac/Intel it will default to linux/amd64 images. In the case of Wasm workloads, the expected target platform is wasi/wasm.

    With Podman we can use the flag --platform=wasi/wasm on the podman build command to specify the system/architecture. But if we do that, it means that if the Dockerfile or Containerfile contains as base image FROM docker.io/redhat/ubi9-minimal, for example, it will try to fetch a ubi9-minimal image using the wasi/wasm platform, but of course it does not exist.

    So, we need to tweak the Containerfile to include a --platform directive inside the Containerfile.

    Example of Containerfile:

    FROM --platform=$BUILDPLATFORM docker.io/redhat/ubi9-minimal as builder
    

    Using this method, we will fetch an image matching our host architecture but as there is still the  --platform=wasi/wasm on the command line, the resulting image will use the right platform.

    Source code​

    Here is a simple Containerfile to build a Rust application using wasm32-wasi binary output and a multi-layer OCI image. One layer for the build (installing Rust, dependencies, and compiling the application) and one scratch layer where we only add the .wasm output and flag it as the entry point.

    Source code is available at https://github.com/redhat-developer/podman-desktop-demo/tree/main/wasm/rust-hello-world.

    Containerfile content:

    # Build using the host platform (and not target platform wasi/wasm)
    FROM --platform=$BUILDPLATFORM docker.io/redhat/ubi9-minimal as builder
    
    # install rust and Wasm/WASI target
    RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
        && source "$HOME/.cargo/env" && rustup target add wasm32-wasi
    
    # copy source code
    COPY Cargo.toml /app/
    COPY src /app/src 
    
    # change working directory
    WORKDIR /app
    
    # Build
    RUN source "$HOME/.cargo/env" && cd /app && cargo build --target wasm32-wasi --release
    
    # now copy the Wasm binary and flag it as the entrypoint
    FROM scratch
    ENTRYPOINT [ "/rust-hello-world.wasm" ]
    COPY --from=builder /app/target/wasm32-wasi/release/rust-hello.wasm /rust-hello-world.wasm
     
    

    The Cargo.toml content:

    [package]
    name = "rust-hello-world"
    version = "0.1.0"
    edition = "2021"
    
    [[bin]]
    name = "rust-hello"
    path = "src/main.rs"
    

    And the Rust program src/main.rs:

      fn main() {
    
        // use of strings literal for multi-line string
        // https://doc.rust-lang.org/reference/tokens.html#raw-string-literals
    
        // ascii art from Máirín Duffy @mairin
        let hello = r#"
    !... Hello Podman Wasm World ...!
    
             .--"--.
           / -     - \
          / (O)   (O) \
       ~~~| -=(,Y,)=- |
        .---. /`  \   |~~
     ~/  o  o \~~~~.----. ~~
      | =(X)= |~  / (O (O) \
       ~~~~~~~  ~| =(Y_)=-  |
      ~~~~    ~~~|   U      |~~
    
    Project:   https://github.com/containers/podman
    Website:   https://podman.io
    Documents: https://docs.podman.io
    Twitter:   @Podman_io
    "#;
        println!("{}", hello);
        
      }
    
    

    All the source code is available at https://github.com/redhat-developer/podman-desktop-demo/tree/main/wasm/rust-hello-world.

    Building Wasm images​

    Run the command from the wasm/rust-hello-world folder if you cloned the repository, or from the directory where all the files are present.

    $ podman build --platform=wasi/wasm -t rust-hello-world-wasm .
    

    Sample output:

    [1/2] STEP 1/6: FROM docker.io/redhat/ubi9-minimal AS builder
    Trying to pull docker.io/redhat/ubi9-minimal:latest...
    Getting image source signatures
    Copying blob sha256:472e9d218c02b84dcd7425232d8b1ac2928602de2de0efc01a7360d1d42bf2f6
    Copying config sha256:317fc66dad246d1fac6996189a26f85554dc9fc92ca23bf1e7bf10e16ead7c8c
    Writing manifest to image destination
    [1/2] STEP 2/6: RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y     && source "$HOME/.cargo/env" && rustup target add wasm32-wasi
    info: downloading installer
    info: profile set to 'default'
    info: default host triple is aarch64-unknown-linux-gnu
    info: syncing channel updates for 'stable-aarch64-unknown-linux-gnu'
    info: latest update on 2023-10-05, rust version 1.73.0 (cc66ad468 2023-10-03)
    info: downloading component 'cargo'
    info: downloading component 'clippy'
    info: downloading component 'rust-docs'
    info: downloading component 'rust-std'
    info: downloading component 'rustc'
    info: downloading component 'rustfmt'
    info: installing component 'cargo'
    info: installing component 'clippy'
    info: installing component 'rust-docs'
    info: installing component 'rust-std'
    info: installing component 'rustc'
    info: installing component 'rustfmt'
    info: default toolchain set to 'stable-aarch64-unknown-linux-gnu'
    
      stable-aarch64-unknown-linux-gnu installed - rustc 1.73.0 (cc66ad468 2023-10-03)
    
    
    Rust is installed now. Great!
    
    To get started you may need to restart your current shell.
    This would reload your PATH environment variable to include
    Cargo's bin directory ($HOME/.cargo/bin).
    
    To configure your current shell, run:
    source "$HOME/.cargo/env"
    info: downloading component 'rust-std' for 'wasm32-wasi'
    info: installing component 'rust-std' for 'wasm32-wasi'
    --> c93a3433d432
    [1/2] STEP 3/6: COPY Cargo.toml /app/
    --> cf4488993835
    [1/2] STEP 4/6: COPY src /app/src
    --> 531b9389857c
    [1/2] STEP 5/6: WORKDIR /app
    --> 23379392f585
    [1/2] STEP 6/6: RUN source "$HOME/.cargo/env" && cd /app && cargo build --target wasm32-wasi --release
       Compiling rust-hello-world v0.1.0 (/app)
        Finished release [optimized] target(s) in 0.15s
    --> e3582e06f45b
    [2/2] STEP 1/3: FROM scratch
    [2/2] STEP 2/3: ENTRYPOINT [ "/rust-hello-world.wasm" ]
    --> 069b1742d906
    [2/2] STEP 3/3: COPY --from=builder /app/target/wasm32-wasi/release/rust-hello.wasm /rust-hello-world.wasm
    [2/2] COMMIT rust-hello-world-wasm
    --> e0948298c0be
    Successfully tagged localhost/rust-hello-world-wasm:latest
    e0948298c0be20e11da5d92646a2d6453f05e66671f72f0f792c1e1ff8de75ba
    

    This is a multi-stage build, but at the end we only have a small image containing the Wasm binary.

    Launch it quickly using:

    $ podman run rust-hello-world-wasm
    

    We'll see the expected output:

    WARNING: image platform (wasi/wasm/v8) does not match the expected platform (linux/arm64)
    
    !... Hello Podman Wasm World ...!
    
             .--"--.
           / -     - \
          / (O)   (O) \
       ~~~| -=(,Y,)=- |
        .---. /`  \   |~~
     ~/  o  o \~~~~.----. ~~
      | =(X)= |~  / (O (O) \
       ~~~~~~~  ~| =(Y_)=-  |
      ~~~~    ~~~|   U      |~~
    
    Project:   https://github.com/containers/podman
    Website:   https://podman.io
    Documents: https://docs.podman.io
    Twitter:   @Podman_io
    
    

    What’s next?​

    After witnessing the seamless execution and creation of WebAssembly (Wasm) workloads on both Windows and macOS through the utilization of Podman, the possibilities are at your fingertips.

    Now, the initiative lies with you to embark on your journey of exploring, experimenting, and pushing the boundaries.

    Run and build new examples, and do not hesitate to contribute to the Podman community by reporting and discussing these issues.

    Note: A big thank you to Máirín Duffy for transforming words into a visual masterpiece with her incredible image with seals and Wasm, adding a touch of magic to this article!

    Related Posts

    • Remote container development with VS Code and Podman

    • Working with Kubernetes in Podman Desktop

    • What is Podman Desktop? A developer's introduction

    • Containerize a Spring Boot application with Podman Desktop

    • How to install and use Podman Desktop on Windows

    • Managing Java containers with Quarkus and Podman Desktop

    Recent Posts

    • Federated identity across the hybrid cloud using zero trust workload identity manager

    • Confidential virtual machine storage attack scenarios

    • Introducing virtualization platform autopilot

    • Integrate zero trust workload identity manager with Red Hat OpenShift GitOps

    • Best Practice Configuration and Tuning for Linux and Windows VMs

    What’s up next?

    Podman in action e-book share image

    Read Podman in Action for easy-to-follow examples to help you learn Podman quickly, including steps to deploy a complete containerized web service.

    Get the e-book
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.