-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #357 from gunamata/expanded-wasm-tutorial
Expanded Wasm tutorial to cover steps from code to Wasm to containers
- Loading branch information
Showing
3 changed files
with
433 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,35 +26,168 @@ For now additional shims can be installed by the user into the `containerd-shims | |
|
||
Any shim installed there will automatically be copied into the VM and configured for the container engine when Rancher Desktop is started (installing a newer version of the `spin` shim will override the bundled version). | ||
|
||
## Running Wasm apps with the container engine | ||
## Developing Wasm Applications with Rancher Desktop | ||
|
||
Running WebAssembly applications directly is currently only supported with the `moby` container engine; there is a bug in `nerdctl` that prevents it from working with `containerd`. | ||
Developing Wasm applications on your local machine on top of Rancher Desktop typically involves below steps: | ||
|
||
The following command runs the `spin-rust-hello` sample `spin` application on the `moby` engine (note the final `/` on the last line; it is the command to run, and `docker run` will fail if it is omitted): | ||
- Create an application in your programming language of choice. You can compile code written in many languages, such as C, C++, Rust, Go, and others, into Wasm modules | ||
- Compile the code into a Wasm module | ||
- Package the Wasm module as a OCI container image and push to a container registry | ||
- Run the Wasm container and/or | ||
- Deploy the Wasm container into Kubernetes | ||
|
||
### Creating a Simple App and Compiling It Into a Wasm Module | ||
|
||
You can use the Spin framework from Fermyon to quickly bootstrap a simple Wasm app. Install Spin on your machine following the instructions on the [Installing Spin](https://developer.fermyon.com/spin/v2/install) page. | ||
|
||
Once you have successfully installed Spin, create a new app via the command `spin new`. | ||
|
||
Select the language you would like to use for development. | ||
```console | ||
$spin new | ||
Pick a template to start your application with: | ||
http-js (HTTP request handler using Javascript) | ||
> http-ts (HTTP request handler using Typescript) | ||
``` | ||
|
||
Give a name to your app | ||
```console | ||
$spin new | ||
Pick a template to start your application with: http-ts (HTTP request handler using Typescript) | ||
Enter a name for your new application: rd-spin-hello-world | ||
``` | ||
|
||
Provide an optional description and leave the API route path to default | ||
```console | ||
$spin new | ||
Pick a template to start your application with: http-ts (HTTP request handler using Typescript) | ||
Enter a name for your new application: rd-spin-hello-world | ||
Description []: This is a simple typescript app that will be compiled into a Wasm module and run as a Wasm container | ||
HTTP path: /... | ||
``` | ||
|
||
Once the command ran successfully, you should see a directory created with the boilerplate code for the Spin app. | ||
|
||
Update the `index.ts` file to return a different message than the default. | ||
|
||
```console | ||
import { HandleRequest, HttpRequest, HttpResponse } from "@fermyon/spin-sdk" | ||
|
||
export const handleRequest: HandleRequest = async function (request: HttpRequest): Promise<HttpResponse> { | ||
return { | ||
status: 200, | ||
headers: { "content-type": "text/plain" }, | ||
body: "Hello from Wasm container!" | ||
} | ||
} | ||
``` | ||
|
||
Change to the app directory and run the `spin build` command to compile the app code into a Wasm module. | ||
|
||
```console | ||
$spin build | ||
Building component rd-spin-hello-world with `npm run build` | ||
|
||
$ [email protected] build | ||
$ npx webpack --mode=production && mkdir -p target && spin js2wasm -o target/rd-spin-hello-world.wasm dist/spin.js | ||
|
||
asset spin.js 4.57 KiB [compared for emit] (name: main) | ||
runtime modules 670 bytes 3 modules | ||
./src/index.ts 2.86 KiB [built] [code generated] | ||
webpack 5.91.0 compiled successfully in 1355 ms | ||
|
||
Starting to build Spin compatible module | ||
Spin compatible module built successfully | ||
Finished building all Spin components | ||
``` | ||
|
||
Once the build command ran successfully, you should see the `rd-spin-hello-world.wasm` module created inside the `target` directory. | ||
|
||
### Package the Wasm Module as an OCI Container Image and Push to a Container Registry | ||
|
||
Create a `Dockerfile` with below code to package the `Wasm` module as a docker image. | ||
|
||
```console | ||
FROM scratch | ||
COPY spin.toml /spin.toml | ||
COPY /target/rd-spin-hello-world.wasm /target/rd-spin-hello-world.wasm | ||
``` | ||
|
||
Run the command below to package the Wasm module as a container image. | ||
|
||
<Tabs groupId="container-runtime"> | ||
<TabItem value="nerdctl" default> | ||
|
||
```console | ||
nerdctl build \ | ||
--namespace k8s.io \ | ||
--platform wasi/wasm \ | ||
-t ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 . | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="docker"> | ||
|
||
```console | ||
docker buildx build \ | ||
--load \ | ||
--platform wasi/wasm \ | ||
--provenance=false \ | ||
-t ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 . | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
Push the image to the container registry | ||
|
||
<Tabs groupId="container-runtime"> | ||
<TabItem value="nerdctl" default> | ||
|
||
```console | ||
nerdctl push ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="docker"> | ||
|
||
```console | ||
docker push ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
### Running the Wasm Container | ||
|
||
Running a Wasm container directly is currently only supported with the `moby` container engine; there is a bug in `nerdctl` that prevents it from working with `containerd`. Ensure you have selected `dockerd(moby)` as the container engine under [Preferences > Container Engine > General](../ui/preferences/container-engine/general.md) to work through the steps in this section. | ||
|
||
|
||
The following command runs the `rd-spin-hello-world` sample `spin` application, built in the previous section, on the `moby` engine (note the final `/` on the last line; it is the command to run, and `docker run` will fail if it is omitted): | ||
|
||
```console | ||
docker run \ | ||
--detach \ | ||
--name spin-demo \ | ||
--runtime io.containerd.spin.v2 \ | ||
--platform wasi/wasm \ | ||
--publish 8080:80 \ | ||
ghcr.io/deislabs/containerd-wasm-shims/examples/spin-rust-hello:v0.11.1 \ | ||
ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 \ | ||
/ | ||
``` | ||
|
||
The internal port `80` has been mapped to `8080` and can be tested from the host: | ||
|
||
``` | ||
$ curl http://localhost:8080/hello | ||
Hello world from Spin! | ||
```console | ||
$ curl http://localhost:8080/ | ||
Hello from Wasm container! | ||
``` | ||
|
||
## Running Wasm apps with Kubernetes | ||
### Running Wasm Apps with Kubernetes | ||
|
||
Running WebAssembly applications on Kubernetes is currently only supported with the `containerd` runtime; it doesn't work with the `cri-dockerd` shim used to run Kubernetes on top of `moby`. | ||
|
||
Create a deployment for the `spin-rust-hello` sample app: | ||
Create a deployment for the sample Wasm container image built in the previous section: | ||
|
||
```console | ||
kubectl apply --filename - <<EOF | ||
|
@@ -75,7 +208,7 @@ spec: | |
runtimeClassName: spin | ||
containers: | ||
- name: hello-spin | ||
image: ghcr.io/deislabs/containerd-wasm-shims/examples/spin-rust-hello:v0.11.1 | ||
image: ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 | ||
command: ["/"] | ||
EOF | ||
``` | ||
|
@@ -132,8 +265,8 @@ ingress.networking.k8s.io/hello-spin created | |
Testing it from the host: | ||
|
||
```console | ||
$ curl http://localhost/hello | ||
Hello world from Spin! | ||
$ curl http://localhost/ | ||
Hello from Wasm container! | ||
``` | ||
|
||
### Ingress IP on Windows | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,11 +26,144 @@ For now additional shims can be installed by the user into the `containerd-shims | |
|
||
Any shim installed there will automatically be copied into the VM and configured for the container engine when Rancher Desktop is started (installing a newer version of the `spin` shim will override the bundled version). | ||
|
||
## Running Wasm apps with the container engine | ||
## Developing Wasm applications with Rancher Desktop | ||
|
||
Running WebAssembly applications directly is currently only supported with the `moby` container engine; there is a bug in `nerdctl` that prevents it from working with `containerd`. | ||
Developing Wasm applications on your local machine on top of Rancher Desktop typically involves below steps: | ||
|
||
The following command runs the `spin-rust-hello` sample `spin` application on the `moby` engine (note the final `/` on the last line; it is the command to run, and `docker run` will fail if it is omitted): | ||
- Create an application in your programming language of choice. You can compile code written in many languages, such as C, C++, Rust, Go, and others, into Wasm modules | ||
- Compile the code into a Wasm module | ||
- Package the Wasm module as a OCI contianer image and push to a container registry | ||
- Run the Wasm container and/or | ||
- Deploy the Wasm container into Kubernetes | ||
|
||
### Creating a simple app and compiling it into a Wasm module | ||
|
||
You can use the Spin framework from Fermyon to quickly bootstrap a simple Wasm app. Install Spin on your machine following the instructions on the [Installing Spin](https://developer.fermyon.com/spin/v2/install) page. | ||
|
||
Once you have successfully installed Spin, create a new app via the command `spin new`. | ||
|
||
Select the lanaguage you would like to use for development. | ||
``` | ||
$spin new | ||
Pick a template to start your application with: | ||
http-js (HTTP request handler using Javascript) | ||
> http-ts (HTTP request handler using Typescript) | ||
``` | ||
|
||
Give a name to your app | ||
``` | ||
$spin new | ||
Pick a template to start your application with: http-ts (HTTP request handler using Typescript) | ||
Enter a name for your new application: rd-spin-hello-world | ||
``` | ||
|
||
Provide an optional description and leave the API route path to default | ||
``` | ||
$spin new | ||
Pick a template to start your application with: http-ts (HTTP request handler using Typescript) | ||
Enter a name for your new application: rd-spin-hello-world | ||
Description []: This is a simple typescript app that will be compiled into a Wasm module and run as a Wasm container | ||
HTTP path: /... | ||
``` | ||
|
||
Once the command ran successfully, you should see a directory created with the boilerplate code for the Spin app. | ||
|
||
Update the `index.ts` file to return a different message than the default. | ||
|
||
``` | ||
import { HandleRequest, HttpRequest, HttpResponse } from "@fermyon/spin-sdk" | ||
export const handleRequest: HandleRequest = async function (request: HttpRequest): Promise<HttpResponse> { | ||
return { | ||
status: 200, | ||
headers: { "content-type": "text/plain" }, | ||
body: "Hello from Wasm container!" | ||
} | ||
} | ||
``` | ||
|
||
Change to the app diretory and run the `spin build` command to compile the app code into a Wasm module. | ||
|
||
``` | ||
$spin build | ||
Building component rd-spin-hello-world with `npm run build` | ||
$ [email protected] build | ||
$ npx webpack --mode=production && mkdir -p target && spin js2wasm -o target/rd-spin-hello-world.wasm dist/spin.js | ||
asset spin.js 4.57 KiB [compared for emit] (name: main) | ||
runtime modules 670 bytes 3 modules | ||
./src/index.ts 2.86 KiB [built] [code generated] | ||
webpack 5.91.0 compiled successfully in 1355 ms | ||
Starting to build Spin compatible module | ||
Spin compatible module built successfully | ||
Finished building all Spin components | ||
``` | ||
|
||
Once the build command ran successfully, you should see the `rd-spin-hello-world.wasm` module created inside the `target` directory. | ||
|
||
### Package the Wasm module as a OCI contianer image and push to a container registry | ||
|
||
Create a `Dockerfile` with below code to package the `Wasm` module as a docker image. | ||
|
||
``` | ||
FROM scratch | ||
COPY spin.toml /spin.toml | ||
COPY /target/rd-spin-hello-world.wasm /target/rd-spin-hello-world.wasm | ||
``` | ||
|
||
Run the command below to package the Wasm module as a container image. | ||
|
||
<Tabs groupId="container-runtime"> | ||
<TabItem value="nerdctl" default> | ||
|
||
``` | ||
nerdctl build \ | ||
--namespace k8s.io \ | ||
--platform wasi/wasm \ | ||
-t ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 . | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="docker"> | ||
|
||
``` | ||
docker buildx build \ | ||
--load \ | ||
--platform wasi/wasm \ | ||
--provenance=false \ | ||
-t ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 . | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
Push the image to the container registry | ||
|
||
<Tabs groupId="container-runtime"> | ||
<TabItem value="nerdctl" default> | ||
|
||
``` | ||
nerdctl push ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="docker"> | ||
|
||
``` | ||
docker push ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
### Running the Wasm container | ||
|
||
Running a Wasm container directly is currently only supported with the `moby` container engine; there is a bug in `nerdctl` that prevents it from working with `containerd`. Ensure you have selected `dockerd(moby)` as the container engine under [Preferences > Container Engine > General](../ui/preferences/container-engine/general.md) to work through the steps in this section. | ||
|
||
|
||
The following command runs the `rd-spin-hello-world` sample `spin` application, built in the previous section, on the `moby` engine (note the final `/` on the last line; it is the command to run, and `docker run` will fail if it is omitted): | ||
|
||
``` | ||
docker run \ | ||
|
@@ -39,22 +172,22 @@ docker run \ | |
--runtime io.containerd.spin.v2 \ | ||
--platform wasi/wasm \ | ||
--publish 8080:80 \ | ||
ghcr.io/deislabs/containerd-wasm-shims/examples/spin-rust-hello:v0.11.1 \ | ||
ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 \ | ||
/ | ||
``` | ||
|
||
The internal port `80` has been mapped to `8080` and can be tested from the host: | ||
|
||
``` | ||
$ curl http://localhost:8080/hello | ||
Hello world from Spin! | ||
$ curl http://localhost:8080/ | ||
Hello from Wasm container! | ||
``` | ||
|
||
## Running Wasm apps with Kubernetes | ||
### Running Wasm apps with Kubernetes | ||
|
||
Running WebAssembly applications on Kubernetes is currently only supported with the `containerd` runtime; it doesn't work with the `cri-dockerd` shim used to run Kubernetes on top of `moby`. | ||
|
||
Create a deployment for the `spin-rust-hello` sample app: | ||
Create a deployment for the sample Wasm container image built in the previous section: | ||
|
||
```console | ||
kubectl apply --filename - <<EOF | ||
|
@@ -75,7 +208,7 @@ spec: | |
runtimeClassName: spin | ||
containers: | ||
- name: hello-spin | ||
image: ghcr.io/deislabs/containerd-wasm-shims/examples/spin-rust-hello:v0.11.1 | ||
image: ghcr.io/rancher-sandbox/rd-spin-hello-world:0.1.0 | ||
command: ["/"] | ||
EOF | ||
``` | ||
|
@@ -132,8 +265,8 @@ ingress.networking.k8s.io/hello-spin created | |
Testing it from the host: | ||
|
||
```console | ||
$ curl http://localhost/hello | ||
Hello world from Spin! | ||
$ curl http://localhost/ | ||
Hello from Wasm container! | ||
``` | ||
|
||
### Ingress IP on Windows | ||
|
Oops, something went wrong.