# Spin (CLI)
A WebAssembly container runtime.

# Why?
Containers are lightweight, portable, and have minimal CPU overhead. However, they require a runtime (e.g., Docker), lack robust isolation, and are not universally portable across different OSes or CPU architectures.

Running containers in a secure and restricted environment is crucial when the code cannot be trusted, such as when it's generated by third parties or AI.

It's also beneficial to have a fallback in case the host operating system lacks a runtime.

Additionally, this enables the embedding of commands and services written in various languages into your code.

# Architecture
`spin` consists of a wasm runtime, an emulator for amd64/riscv64 compiled to wasm, and a minimal OS image that launches your container inside the emulator.

# Install
Currently, you must compile `spin` yourself by running `go build .`:
```sh
git clone https://github.com/taubyte/tau.git
cd tools/spin
go build .
```

# Usage
If you would like to incorporate `spin` into your project, refer to the [`pkg/spin/README.md`](../../pkg/spin/README.md).

### Pull
```sh
spin pull amd64/alpine:edge
```
Images are compressed using Squashfs. Currently, this step may take a few minutes as `mksquashfs` is run using `spin`, which is CPU intensive.

### Run
```sh
spin run --arch <arch> <image>
```

### Examples
#### Run shell
```sh
spin run --arch riscv64 riscv64/alpine:edge
```

#### Run command
```sh
spin run --arch riscv64 riscv64/alpine:edge ls
```

#### Mount a folder
```sh
spin run --arch riscv64 --mount .:/src riscv64/alpine:edge
```
Note: wasi does not export permissions.


#### Export Environment variables
```sh
spin run --arch riscv64 --env SPIN=IsAwesome riscv64/alpine:edge sh -c "echo \$SPIN"
```

Outputs,
```
IsAwesome
```

#### Different platforms
##### RISC-V 64
```
$ spin run --arch riscv64 riscv64/alpine:edge uname -a
Linux localhost 6.1.0 #1 Sun Aug 18 22:29:26 UTC 2024 riscv64 Linux
```

##### AMD64
```
$ spin run --arch amd64 amd64/alpine:edge uname -a
Linux localhost 6.1.0 #1 PREEMPT_DYNAMIC Sun Aug 18 23:43:24 UTC 2024 x86_64 Linux
```

#### Run a service
```sh
spin run --zip fixtures/network-test-containers.zip --module network-test-container.wasm --port 8080:8080 --no-stdin --net
```
Wait for it to print `STARTED`, then curl it:
```sh
curl http://127.0.0.1:8080
```

Output:
```
Hello, World!
```

# Limitations
## Performance
Currently, WebAssembly is single-threaded, so only one CPU can be emulated. Generally, expect execution speeds to be about 10 times slower than native code on a single core.

## Memory
WebAssembly modules cannot address more than 4GB and [wizer](https://github.com/bytecodealliance/wizer) is having a hard time optimizing the module when the memory exceeds 1GB. Thus, the runtime is presently limited to 1GB. Plans include using swap files that are in-memory on the host side to increase container memory in the future.
