{"id":96386,"date":"2024-09-25T08:00:00","date_gmt":"2024-09-25T15:00:00","guid":{"rendered":"https:\/\/opensource.microsoft.com\/blog\/?p=96386"},"modified":"2024-11-05T14:22:18","modified_gmt":"2024-11-05T22:22:18","slug":"distributing-webassembly-components-using-oci-registries","status":"publish","type":"post","link":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/","title":{"rendered":"Distributing WebAssembly components using OCI registries\u00a0"},"content":{"rendered":"\n<p>Containers are the de facto<em> <\/em>standard for packaging, distributing, and running applications in the cloud-native world. As the cloud-native space keeps evolving at a rapid pace, WebAssembly (Wasm) is emerging as a promising light weight, secure, and portable alternative to containers. But where do you store your Wasm components?&nbsp;&nbsp;<\/p>\n\n\n\n<p>Containers have a standard storage mechanism so universal we forget about it: Open Container Initiative (OCI) registries like Microsoft Azure Container Registry, GitHub Container Registry (GHCR), or Docker Hub. Wouldn\u2019t it be cool if Wasm components could be used easily with OCI registries, too?&nbsp;<\/p>\n\n\n\n<p>The <a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/charter\/\" target=\"_blank\" rel=\"noreferrer noopener\">CNCF (Cloud Native Computing Foundation) Wasm Working Group<\/a> thought so and came together to define a <a><\/a><a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/deliverables\/wasm-oci-artifact\" target=\"_blank\" rel=\"noreferrer noopener\">format for Wasm OCI Artifacts<\/a>. Now, you can use any OCI registry to store and use your WebAssembly components, just like you do with containers.&nbsp;<\/p>\n\n\n<div class=\"wp-block-msxcm-cta-block\" data-moray data-bi-an=\"CTA Block\">\n\t<div class=\"card d-block mx-ng mx-md-0\">\n\t\t<div class=\"row no-gutters material-color-brand-light bg-fabric-white\">\n\n\t\t\t\t\t\t\t<div class=\"col-md-4\">\n\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"600\" src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/4.24-cta.png\" class=\"card-img img-object-cover\" alt=\"developer looking at code\" srcset=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/4.24-cta.webp 600w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/4.24-cta-388x388.webp 388w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/4.24-cta-150x150.webp 150w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/4.24-cta-450x450.webp 450w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/>\t\t\t\t<\/div>\n\t\t\t\n\t\t\t<div class=\"d-flex col-md\">\n\t\t\t\t<div class=\"card-body align-self-center p-4 p-md-5\">\n\t\t\t\t\t\n\t\t\t\t\t<h2>WebAssembly Working Group Charter<\/h2>\n\n\t\t\t\t\t<div class=\"mb-3\">\n\t\t\t\t\t\t<p>Run workloads in a diverse set of environments in both a centralized location and at the edge.<\/p>\n\t\t\t\t\t<\/div>\n\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"link-group\">\n\t\t\t\t\t\t\t<a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/charter\/\" class=\"btn btn-link text-decoration-none p-0\" target=\"_blank\">\n\t\t\t\t\t\t\t\t<span>Learn more<\/span>\n\t\t\t\t\t\t\t\t<span class=\"glyph-append glyph-append-chevron-right glyph-append-xsmall\"><\/span>\n\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\n\t\t\t\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n\n<p>In this article, we&#8217;ll cover:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Why OCI registries are fantastic to retrieve and deploy WebAssembly components.<\/li>\n\n\n\n<li>How to create a Wasm component in Rust and push it to GitHub Container Registry.&nbsp;<\/li>\n\n\n\n<li>How to pull your component and run it using the <a href=\"https:\/\/wasmtime.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">wasmtime<\/a>, a WebAssembly runtime.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"advantages-of-oci-with-wasm\">Advantages of OCI with Wasm&nbsp;<\/h2>\n\n\n\n<p>Wasm, introduced in 2015, was originally designed as a compilation target for web applications, focusing on portability, safety, and efficiency. These same features make Wasm attractive for the server side, and recently, the introduction of Wasm components and the standardization of <a href=\"https:\/\/wasi.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">WebAssembly System Interface (WASI)<\/a> has begun to make it possible to use Wasm components in server-side applications through public interfaces like <a href=\"https:\/\/github.com\/WebAssembly\/WASI\/blob\/main\/Proposals.md#active-proposals\" target=\"_blank\" rel=\"noreferrer noopener\">wasi-http, wasi-filesystem, and more<\/a><a><\/a>.&nbsp;<\/p>\n\n\n\n<p>The brilliance of the container ecosystem lies in its comprehensive end-to-end experience for developers, particularly through packaging and distribution according to the <a href=\"https:\/\/opencontainers.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Open Container Initiative<\/a> specifications. OCI provides a standard for container formats and runtimes, with one of its main attributes being the image format. The newly released <a href=\"https:\/\/opencontainers.org\/posts\/blog\/2024-03-13-image-and-distribution-1-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">OCI 1.1 specification<\/a> includes Artifact support, which allows you to package <strong>any type of content<\/strong>, not just containers, and distribute to your registries in a way that&#8217;s familiar to anyone using containers.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Utilizing OCI Artifacts, the <a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/deliverables\/wasm-oci-artifact\" target=\"_blank\" rel=\"noreferrer noopener\">new Wasm Artifact format<\/a> allows you to use both Wasm components and containers across all the major cloud providers in the same fundamental way. Moreover, because Wasm does not require a specific operating system (OS) type or architecture to execute, a single component image can be run anywhere a Wasm runtime is available. There&#8217;s no need for multiarch build continuous integration and continuous delivery (CI\/CD) pipelines for Wasm OCI Artifacts.&nbsp;<\/p>\n\n\n\n<p>Many projects are already taking advantage of this work. Projects like <a><\/a><a href=\"https:\/\/github.com\/fermyon\/spin\" target=\"_blank\" rel=\"noreferrer noopener\">Spin<\/a>, the containerd project <a href=\"https:\/\/github.com\/containerd\/runwasi\" target=\"_blank\" rel=\"noreferrer noopener\">runwasi<\/a>, and <a href=\"https:\/\/github.com\/wasmCloud\/wasmCloud\" target=\"_blank\" rel=\"noreferrer noopener\">wasmCloud<\/a> have already begun to integrate Wasm OCI Artifacts\u2014making the standard useful across the open-source ecosystem. Let us look at how Wasm OCI Artifacts are used to develop and run applications.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"developing-a-wasm-application-using-cargo-component\">Developing a Wasm application using cargo-component&nbsp;<\/h2>\n\n\n\n<p>For languages, one of the most interesting use cases is to share functionality. C uses \u201cheader\u201d files to accomplish this, and in the case of Wasm, the analogue is the Wasm component&#8217;s interface definition language, called <a href=\"https:\/\/component-model.bytecodealliance.org\/design\/wit.html\">WebAssembly Interface Types<\/a> (WIT), which can also be packaged as an OCI image. As a result, you can use your language tools like\u202fRust\u2019s cargo-component\u202fto dynamically fetch the interfaces needed to implement Wasm components\u2014instead of manually copying the files locally.&nbsp;<\/p>\n\n\n\n<p>This section will focus on creating a Rust application that compiles to a Wasm component targeting the wasi-http world using Wasm OCI Artifacts.&nbsp;&nbsp;&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-your-environment\">Setting up your environment&nbsp;<\/h3>\n\n\n\n<p>First, let&#8217;s set up the environment. We&#8217;ll be building our application in <a href=\"https:\/\/www.rust-lang.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Rust<\/a> and assume <a href=\"https:\/\/www.rust-lang.org\/tools\/install\" target=\"_blank\" rel=\"noreferrer noopener\">Rust is already installed<\/a>.&nbsp; We&#8217;ll need a few tools:&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/bytecodealliance\/cargo-component\" target=\"_blank\" rel=\"noreferrer noopener\">cargo-component<\/a>\u2014a subcommand for Cargo to build Wasm components and include the Wasi target for rust.&nbsp;&nbsp;<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/bytecodealliance\/wasm-pkg-tools\" target=\"_blank\" rel=\"noreferrer noopener\">wkg<\/a>\u2014to push\/pull Wasm OCI Artifacts.<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/bytecodealliance\/wasm-tools\" target=\"_blank\" rel=\"noreferrer noopener\">wasm-tools<\/a>\u2014to parse Wasm components. wasm-tools\u202fcan also be used to debug and understand Wasm modules and components.&nbsp;&nbsp;<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/bytecodealliance\/wasmtime\" target=\"_blank\" rel=\"noreferrer noopener\">wasmtime<\/a>\u2014a runtime that we will use to test the component locally.<\/li>\n<\/ul>\n\n\n\n<p>You can install these tools by running the following commands:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ncargo install cargo-component@0.16.0\u00a0\nrustup target add wasm32-wasi \ncargo install wasm-tools@1.216.0 \ncargo install wkg@0.5.1 \ncurl https:\/\/wasmtime.dev\/install.sh -sSf | bash \n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"creating-a-rust-component-project\">Creating a Rust Component Project&nbsp;<\/h3>\n\n\n\n<p>Create a new Rust project for Wasm components using the following commands, and then remove the example WIT file that is created:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ncargo component new --lib hello-wasi-http --proxy \ncd hello-wasi-http\/ \nrm -r wit \n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"creating-a-http-handler-component\">Creating a HTTP handler component&nbsp;<\/h3>\n\n\n\n<p>Prior to cargo-component v0.16.0, projects had to copy and paste the files from the Bytecode Alliance WIT GitHub files to a WIT folder in their local project\u2014similar to adding .h files to a C project. Now, you can use a single command in <a href=\"https:\/\/github.com\/bytecodealliance\/cargo-component\/pull\/322\" target=\"_blank\" rel=\"noreferrer noopener\">cargo-component<\/a> to obtain the WIT interface files directly from Wasm OCI Artifacts. Our friends in the Bytecode Alliance have published all the Wasi WIT world files to <a href=\"https:\/\/github.com\/orgs\/WebAssembly\/packages\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub Packages Registry<\/a> as OCI Artifacts.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Now, we can use Rust\u2019s Wasm integration to generate the Rust code to use the wasi:http\/proxy world. The bindings for the types are generated at compile time from the WIT files when cargo-component build is called. To enable this, we need to add wasi:http as a component target. Append the following to the bottom of your Cargo.toml file:&nbsp;&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n[package.metadata.component.target] \npackage = \"wasi:http\" \nversion = \"0.2.0\" \nworld = \"proxy\" \n<\/pre><\/div>\n\n\n<p>Now, you need to implement the Hypertext Transfer Protocol&nbsp;(HTTP) incoming handler interface. In particular, to target the wasi-http WIT world, your component needs to export an\u202fincoming handler\u202finterface, and this is created by cargo-component with the bindings::exports::wasi::http::incoming_handler::Guest\u202ftrait, which has a single method of signature defined in WIT as \u202ffn handle(request: IncomingRequest, outparam: ResponseOutparam).&nbsp;<\/p>\n\n\n\n<p>To implement the interface, open\u202fsrc\/lib.rs\u202fin your text editor and replace the entire file with the following:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n#[allow(warnings)] \nmod bindings; \npub use bindings::wasi::http::types::{ \n    Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam, \n}; \nstruct Component; \nbindings::export!(Component with_types_in bindings); \nimpl bindings::exports::wasi::http::incoming_handler::Guest for Component { \n    fn handle(_request: IncomingRequest, outparam: ResponseOutparam) { \n        let hdrs = Fields::new(); \n        let resp = OutgoingResponse::new(hdrs); \n        let body = resp.body().expect(\"outgoing response\"); \n        ResponseOutparam::set(outparam, Ok(resp)); \n        let out = body.write().expect(\"outgoing stream\"); \n        out.blocking_write_and_flush(b\"Hello, this is your first wasi:http\/proxy world!\\n\") \n            .expect(\"writing response\"); \n        drop(out); \n        OutgoingBody::finish(body, None).unwrap(); \n    } \n} \n<\/pre><\/div>\n\n\n<p>You may find this paradigm resembles serverless computing, and it does. The HTTP server is managed by the host that runs this Wasm component, delegating the HTTP request handling to your handler function.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"build-and-run-this-component-locally\">Build and run this component locally&nbsp;<\/h3>\n\n\n\n<p>To build your component, you can run:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ncargo component build --release \nmv target\/wasm32-wasip1\/release\/hello_wasi_http.wasm .\/hello_wasi_http.wasm \n<\/pre><\/div>\n\n\n<p>This will produce a Wasm component called\u202fhello_wasi_http.wasm. You may see that the produced component is only about 64kB. Sure, it is a hello world program, but that is still <strong>very small<\/strong>.&nbsp;<\/p>\n\n\n\n<p>If you run wasm-tools component with hello_wasi_http.wasm, you can see that it exports wasi:http\/incoming-handler@0.2.0,\u202fwhich you just implemented in the last section.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Next, let us run this component locally using wasmtime, an open-source Wasm runtime from the Bytecode Alliance:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nwasmtime serve hello_wasi_http.wasm\u00a0\u00a0\n<\/pre><\/div>\n\n\n<p>This will serve HTTP requests on local host at port 3000. Open a new terminal and run the following command to verify that your component is working properly:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n> curl 127.0.0.1:3000\u00a0\n<\/pre><\/div>\n\n\n<p>Hello, this is your first wasi:http\/proxy world!<\/p>\n\n\n\n<p>You have successfully built and run your first Wasm component with the help of a Wasm OCI Artifact.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-magic-package-push-and-pull-wasm-app-to-and-from-github-container-registry-as-oci-artifact\">The magic: Package, push, and pull Wasm app to and from GitHub Container Registry as OCI Artifact&nbsp;<\/h2>\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/high-res-9.23.webp\" alt=\"Building, pushing and viewing the Wasm OCI Artifact\" class=\"wp-image-96418 webp-format\" style=\"width:728px;height:auto\" srcset=\"\" data-orig-src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/high-res-9.23.webp\"><\/figure>\n\n\n\n<p>Now that we&#8217;ve built an application by consuming WIT OCI Artifacts, let&#8217;s publish it so it can be run by a compatible runtime.&nbsp;<\/p>\n\n\n\n<p>First, log in into\u202f<a href=\"https:\/\/docs.github.com\/en\/packages\/working-with-a-github-packages-registry\/working-with-the-container-registry#pushing-container-images\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub Container Registry<\/a>. Once logged in, we can use the following wkg cli to turn our Wasm component we built previously into an OCI Artifact and push it to GHCR:&nbsp;<\/p>\n\n\n\n<p><code>wkg oci push ghcr.io\/&lt;your_github_username&gt;\/hello-wasi-http:latest hello_wasi_http.wasm&nbsp;<\/code><\/p>\n\n\n\n<p>Let&#8217;s look directly at the format for the new artifact we have published. You can use <a href=\"https:\/\/github.com\/regclient\/regclient\" target=\"_blank\" rel=\"noreferrer noopener\">regctl<\/a> (or your favorite image inspection client) to inspect the artifact, looking for the digest value of the Config entry:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nregctl manifest get ghcr.io\/<your_github_username>\/hello-wasi-http:latest\u00a0\n\n<snip>\u00a0\n\nConfig:\u00a0\n\n\u00a0 Digest:\u00a0\u00a0\u00a0 sha256:66305959b88c33eb660c78bed6e9e06ec809a38f06f89a9ddf5b0cb8b22f0c0c\u00a0\n\n\u00a0 MediaType: application\/vnd.wasm.config.v0+json\u00a0\n\n\u00a0 Size:\u00a0\u00a0\u00a0\u00a0\u00a0 413B\u00a0\n\nLayers:\u00a0\n\n\u00a0 Digest:\u00a0\u00a0\u00a0 sha256:a31c2628694eb560dd0e8f82de12e657268c761727c3ad98638c9c55dd46c5df\u00a0\n\n\u00a0 MediaType: application\/wasm\u00a0\n\n\u00a0 Size:\u00a0\u00a0\u00a0\u00a0\u00a0 87818B\n<\/pre><\/div>\n\n\n<p>Here, we can see the two important parts: the\u202fconfig.mediaType of application\/vnd.wasm.config.v0+json and the layers with\u202f&#8221;mediaType&#8221;:&#8221;application\/wasm&#8221;,\u202fboth of which are <a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/deliverables\/wasm-oci-artifact\/\">defined here<\/a>.<\/p>\n\n\n\n<p>Let&#8217;s take look at the\u202fconfig.mediaType\u202ffor Wasm using the Digest value and pipe that to \u201cjq.\u201d:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nregctl blob get ghcr.io\/<your_github_username>\/hello-wasi-http:latest sha256:66305959b88c33eb660c78bed6e9e06ec809a38f06f89a9ddf5b0cb8b22f0c0c | jq\u00a0\n\n{\u00a0\n\n\u00a0 \"created\": \"2024-07-26T21:56:17.581533530Z\",\u00a0\n\n\u00a0 \"author\": null,\u00a0\n\n\u00a0 \"architecture\": \"wasm\",\u00a0\n\n\u00a0 \"os\": \"wasip2\",\u00a0\n\n\u00a0 \"layerDigests\": [\u00a0\n\n\u00a0\u00a0\u00a0 \"sha256:a31c2628694eb560dd0e8f82de12e657268c761727c3ad98638c9c55dd46c5df\"\u00a0\n\n\u00a0 ],\u00a0\n\n\u00a0 \"component\": {\u00a0\n\n\u00a0\u00a0\u00a0 \"exports\": [\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:http\/incoming-handler@0.2.0\"\u00a0\n\n\u00a0\u00a0\u00a0 ],\u00a0\n\n\u00a0\u00a0\u00a0 \"imports\": [\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:io\/error@0.2.0\",\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:io\/streams@0.2.0\",\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:http\/types@0.2.0\",\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:cli\/stdout@0.2.0\",\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:cli\/stderr@0.2.0\",\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0 \"wasi:cli\/stdin@0.2.0\"\u00a0\n\n\u00a0\u00a0\u00a0 ],\u00a0\n\n\u00a0\u00a0\u00a0 \"target\": null\u00a0\n\n\u00a0 }\u00a0\n\n}\n<\/pre><\/div>\n\n\n<p>This should look familiar. The exports and imports are the same as the WIT we were using to build our application\u202fhttp\/incoming-handler@0.2.0.&nbsp;<\/p>\n\n\n\n<p>The Wasm\u202fconfig.mediaType\u202fconfiguration provides the ability to quickly identify imports, exports, or worlds that are used by the component. The full explanation for the format can be <a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/deliverables\/wasm-oci-artifact\/\">found here<\/a>. Since all of this information is exposed in the configuration, it also means we can use existing tools to search and find other Wasm components in Container Registries\u2014now that\u2019s something new!&nbsp;<\/p>\n\n\n\n<p>Now that we have it pushed to the registry, we can pull it down and run it in a runtime:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nwkg oci pull ghcr.io\/<your_github_username>\/hello-wasi-http:latest -o app.wasm\u00a0\n\nSuccessfully wrote ghcr.io\/<your_github_username>\/hello-wasi-http:latest to app.wasm\u00a0\n\nwasmtime serve hello_wasi_http.wasm --addr 127.0.0.1:3000\n<\/pre><\/div>\n\n\n<p>We\u2019ve just successfully packaged, pushed, and pulled a Wasm component as an OCI Artifact.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"moving-into-the-future-of-oci-registries\">Moving into the future of OCI registries<\/h2>\n\n\n\n<p>Since Wasm Artifacts follow the OCI 1.1 specification, you are not limited to GitHub Container Registry. You can use any of your existing registries and also use investments you&#8217;ve made into image signing and software bill of materials (SBOM) support.&nbsp;<\/p>\n\n\n\n<p>The exciting aspects about this common OCI Artifact format for Wasm are the consistency it enables for tools across the ecosystem and the fact that Wasm OCI compatibility will be built directly into the language tooling such as cargo-component, <a href=\"https:\/\/github.com\/bytecodealliance\/componentize-dotnet\" target=\"_blank\" rel=\"noreferrer noopener\">dotnet<\/a>, and <a href=\"https:\/\/github.com\/bytecodealliance\/wasm-tools-go\" target=\"_blank\" rel=\"noreferrer noopener\">go<\/a>.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Please try using Rust to create and run a WebAssembly component and store it and deploy it using OCI Artifacts\u2014and provide feedback or get involved by helping your favorite language or tool add support for the OCI package format.&nbsp;You can reach out to any of the projects mentioned in the article or join us in the <a href=\"https:\/\/tag-runtime.cncf.io\/wgs\/wasm\/charter\/\" target=\"_blank\" rel=\"noreferrer noopener\">CNCF wasm working group.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>As the cloud-native space keeps evolving at a rapid pace, WebAssembly is emerging as a promising alternative to containers.<\/p>\n","protected":false},"author":6236,"featured_media":96390,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"msxcm_post_with_no_image":false,"ep_exclude_from_search":false,"_classifai_error":"","_classifai_text_to_speech_error":"","footnotes":""},"post_tag":[],"content-type":[340],"topic":[2242],"programming-languages":[2268],"coauthors":[2585,2584],"class_list":["post-96386","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","content-type-tutorials-and-demos","topic-containers","programming-languages-rust","review-flag-1593580428-734","review-flag-1593580419-521","review-flag-1-1593580432-963","review-flag-2-1593580437-411","review-flag-5-1593580453-725","review-flag-anywh-1593580318-567","review-flag-integ-1593580288-449","review-flag-new-1593580248-669"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Distributing WebAssembly components using OCI registries\u00a0 | Microsoft Open Source Blog<\/title>\n<meta name=\"description\" content=\"Learn to integrate Wasm OCI Artifacts leveraging the power of OCI registries to simplify deployment of WebAssembly components across the cloud-native ecosystem.\u202fLearn more\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Distributing WebAssembly components using OCI registries\u00a0 | Microsoft Open Source Blog\" \/>\n<meta property=\"og:description\" content=\"Learn to integrate Wasm OCI Artifacts leveraging the power of OCI registries to simplify deployment of WebAssembly components across the cloud-native ecosystem.\u202fLearn more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\" \/>\n<meta property=\"og:site_name\" content=\"Microsoft Open Source Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-09-25T15:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-11-05T22:22:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1260\" \/>\n\t<meta property=\"og:image:height\" content=\"840\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Joe Zhou, James Sturtevant\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@OpenAtMicrosoft\" \/>\n<meta name=\"twitter:site\" content=\"@OpenAtMicrosoft\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joe Zhou, James Sturtevant\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 min read\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\"},\"author\":[{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/author\/joe-zhou\/\",\"@type\":\"Person\",\"@name\":\"Joe Zhou\"},{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/author\/james-sturtevant\/\",\"@type\":\"Person\",\"@name\":\"James Sturtevant\"}],\"headline\":\"Distributing WebAssembly components using OCI registries\u00a0\",\"datePublished\":\"2024-09-25T15:00:00+00:00\",\"dateModified\":\"2024-11-05T22:22:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\"},\"wordCount\":1590,\"publisher\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg\",\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\",\"name\":\"Distributing WebAssembly components using OCI registries\u00a0 | Microsoft Open Source Blog\",\"isPartOf\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg\",\"datePublished\":\"2024-09-25T15:00:00+00:00\",\"dateModified\":\"2024-11-05T22:22:18+00:00\",\"description\":\"Learn to integrate Wasm OCI Artifacts leveraging the power of OCI registries to simplify deployment of WebAssembly components across the cloud-native ecosystem.\u202fLearn more\",\"breadcrumb\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg\",\"contentUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg\",\"width\":1260,\"height\":840,\"caption\":\"developer on computer\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/opensource.microsoft.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Distributing WebAssembly components using OCI registries\u00a0\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#website\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/\",\"name\":\"Microsoft Open Source Blog\",\"description\":\"Open dialogue about openness at Microsoft \u2013 open source, standards, interoperability\",\"publisher\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/opensource.microsoft.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#organization\",\"name\":\"Microsoft Open Source Blog\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png\",\"contentUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png\",\"width\":259,\"height\":194,\"caption\":\"Microsoft Open Source Blog\"},\"image\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/OpenAtMicrosoft\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Distributing WebAssembly components using OCI registries\u00a0 | Microsoft Open Source Blog","description":"Learn to integrate Wasm OCI Artifacts leveraging the power of OCI registries to simplify deployment of WebAssembly components across the cloud-native ecosystem.\u202fLearn more","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/","og_locale":"en_US","og_type":"article","og_title":"Distributing WebAssembly components using OCI registries\u00a0 | Microsoft Open Source Blog","og_description":"Learn to integrate Wasm OCI Artifacts leveraging the power of OCI registries to simplify deployment of WebAssembly components across the cloud-native ecosystem.\u202fLearn more","og_url":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/","og_site_name":"Microsoft Open Source Blog","article_published_time":"2024-09-25T15:00:00+00:00","article_modified_time":"2024-11-05T22:22:18+00:00","og_image":[{"width":1260,"height":840,"url":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg","type":"image\/jpeg"}],"author":"Joe Zhou, James Sturtevant","twitter_card":"summary_large_image","twitter_creator":"@OpenAtMicrosoft","twitter_site":"@OpenAtMicrosoft","twitter_misc":{"Written by":"Joe Zhou, James Sturtevant","Est. reading time":"8 min read"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#article","isPartOf":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/"},"author":[{"@id":"https:\/\/opensource.microsoft.com\/blog\/author\/joe-zhou\/","@type":"Person","@name":"Joe Zhou"},{"@id":"https:\/\/opensource.microsoft.com\/blog\/author\/james-sturtevant\/","@type":"Person","@name":"James Sturtevant"}],"headline":"Distributing WebAssembly components using OCI registries\u00a0","datePublished":"2024-09-25T15:00:00+00:00","dateModified":"2024-11-05T22:22:18+00:00","mainEntityOfPage":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/"},"wordCount":1590,"publisher":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#organization"},"image":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage"},"thumbnailUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg","inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/","url":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/","name":"Distributing WebAssembly components using OCI registries\u00a0 | Microsoft Open Source Blog","isPartOf":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage"},"image":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage"},"thumbnailUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg","datePublished":"2024-09-25T15:00:00+00:00","dateModified":"2024-11-05T22:22:18+00:00","description":"Learn to integrate Wasm OCI Artifacts leveraging the power of OCI registries to simplify deployment of WebAssembly components across the cloud-native ecosystem.\u202fLearn more","breadcrumb":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#primaryimage","url":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg","contentUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/09\/9.19-featured-image.jpg","width":1260,"height":840,"caption":"developer on computer"},{"@type":"BreadcrumbList","@id":"https:\/\/opensource.microsoft.com\/blog\/2024\/09\/25\/distributing-webassembly-components-using-oci-registries\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/opensource.microsoft.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Distributing WebAssembly components using OCI registries\u00a0"}]},{"@type":"WebSite","@id":"https:\/\/opensource.microsoft.com\/blog\/#website","url":"https:\/\/opensource.microsoft.com\/blog\/","name":"Microsoft Open Source Blog","description":"Open dialogue about openness at Microsoft \u2013 open source, standards, interoperability","publisher":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/opensource.microsoft.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/opensource.microsoft.com\/blog\/#organization","name":"Microsoft Open Source Blog","url":"https:\/\/opensource.microsoft.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png","contentUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png","width":259,"height":194,"caption":"Microsoft Open Source Blog"},"image":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/OpenAtMicrosoft"]}]}},"msxcm_display_generated_audio":false,"msxcm_animated_featured_image":null,"distributor_meta":false,"distributor_terms":false,"distributor_media":false,"distributor_original_site_name":"Microsoft Open Source Blog","distributor_original_site_url":"https:\/\/opensource.microsoft.com\/blog","push-errors":false,"_links":{"self":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts\/96386","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/users\/6236"}],"replies":[{"embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/comments?post=96386"}],"version-history":[{"count":19,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts\/96386\/revisions"}],"predecessor-version":[{"id":96421,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts\/96386\/revisions\/96421"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/media\/96390"}],"wp:attachment":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/media?parent=96386"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/post_tag?post=96386"},{"taxonomy":"content-type","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/content-type?post=96386"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/topic?post=96386"},{"taxonomy":"programming-languages","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/programming-languages?post=96386"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/coauthors?post=96386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}