Before you begin, you need to have the following installed:
- Docker version 4.13.1 (90346) or later with containerd enabled
- k3d
- kubectl
- Spin v2.0+ and templates
- Rust 1.71+
Start a k3d cluster with the wasm shims already installed:
k3d cluster create wasm-cluster --image ghcr.io/deislabs/containerd-wasm-shims/examples/k3d:v0.11.1 -p "8081:80@loadbalancer" --agents 2 --registry-create mycluster-registry:12345
Apply RuntimeClass for spin applications to use the spin wasm shim:
kubectl apply -f https://raw.githubusercontent.com/deislabs/containerd-wasm-shims/main/deployments/workloads/runtime.yaml
Deploy a pre-built sample spin application:
kubectl apply -f https://raw.githubusercontent.com/deislabs/containerd-wasm-shims/main/deployments/workloads/workload.yaml
echo "waiting 5 seconds for workload to be ready"
sleep 5
curl -v http://0.0.0.0:8081/spin/hello
Confirm you see a response from the sample application. For example:
$ curl -v http://0.0.0.0:8081/spin/hello
* Trying 0.0.0.0:8081...
* TCP_NODELAY set
* Connected to 0.0.0.0 (127.0.0.1) port 8081 (#0)
> GET /hello HTTP/1.1
> Host: 0.0.0.0:8081
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Length: 22
< Date: Mon, 10 Oct 2022 20:39:43 GMT
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 0.0.0.0 left intact
Hello world from Spin!
Delete the pre-built sample spin application:
kubectl delete -f https://raw.githubusercontent.com/deislabs/containerd-wasm-shims/main/deployments/workloads/workload.yaml
Use spin
to create a new sample application based on the http-rust
template:
spin new -t http-rust qs-wasm-spin
Add the details when prompted. For example:
$ spin new -t http-rust qs-wasm-spin
Description: An example app for the quickstart
HTTP path: /hi
Navigate to the directory where you created the application:
cd qs-wasm-spin
Use rustup
to install the wasm32-wasi
target and spin build
to build the application. For example:
rustup target add wasm32-wasi
spin build
Use spin up
to run the application on your development computer. For example:
spin up
The output shows the url for accessing the application. For example:
$ spin up
Serving http://127.0.0.1:3000
Available Routes:
qs-wasm-spin: http://127.0.0.1:3000/hi
Access the /hi
route. For example, use curl
in a new terminal window:
$ curl http://127.0.0.1:3000/hi
Hello, Fermyon
Return to the terminal window running spin up
and stop the application.
You have two choices for publishing spin apps. The steps to deploy are the same afterwards.
- Container image - use
docker build
to build a container image. This is a standard container image with the Spin application files in the root directory. - OCI WASM image - use
spin registry push
to publish to OCI registry. This is a WASM specific image format that contains custom layers for the spin files. Requires Spin 2.0+ and containerd 1.7.7+.
Create a Dockerfile
at the root of the application directory with the following:
FROM --platform=${BUILDPLATFORM} rust:1.71 AS build
WORKDIR /opt/build
COPY . .
RUN rustup target add wasm32-wasi && cargo build --target wasm32-wasi --release
FROM scratch
COPY --from=build /opt/build/target/wasm32-wasi/release/qs_wasm_spin.wasm .
COPY --from=build /opt/build/spin.toml .
Update spin.toml
to change source
to qs_wasm_spin.wasm
:
...
[component.qs-wasm-spin]
source = "qs_wasm_spin.wasm"
...
Use docker
to build the container image and push it to the k3d registry:
docker buildx build --platform=wasi/wasm -t localhost:12345/qs-wasm-spin .
docker push localhost:12345/qs-wasm-spin:latest
It is possible to publish spin applications to OCI registries.
# must be spin 2.0
spin registry push localhost:12345/spin-wasm-shim:latest-2.0
Create a qs.yaml
file with the following:
apiVersion: apps/v1
kind: Deployment
metadata:
name: wasm-spin
spec:
replicas: 3
selector:
matchLabels:
app: wasm-spin
template:
metadata:
labels:
app: wasm-spin
spec:
runtimeClassName: wasmtime-spin
containers:
- name: testwasm
image: mycluster-registry:12345/qs-wasm-spin:latest
command: ["/"]
---
apiVersion: v1
kind: Service
metadata:
name: wasm-spin
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: wasm-spin
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wasm-spin
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: traefik
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wasm-spin
port:
number: 80
Deploy the application and confirm it is running:
kubectl apply -f qs.yaml
echo "waiting 5 seconds for workload to be ready"
sleep 5
curl -v http://0.0.0.0:8081/hi
Confirm you see a response from the sample application. For example:
$ curl -v http://0.0.0.0:8081/hi
* Trying 0.0.0.0:8081...
* TCP_NODELAY set
* Connected to 0.0.0.0 (127.0.0.1) port 8081 (#0)
> GET /hi HTTP/1.1
> Host: 0.0.0.0:8081
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Length: 14
< Date: Tue, 11 Oct 2022 02:23:32 GMT
< Foo: bar
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 0.0.0.0 left intact
Hello, Fermyon
Remove the sample application:
kubectl delete -f qs.yaml
Delete the cluster:
k3d cluster delete wasm-cluster
Try running Wasm applications on Docker Desktop or on Kubernetes, such as AKS.