Skip to content

Commit

Permalink
feat(examples): Add Rust examples
Browse files Browse the repository at this point in the history
Add Rocket, Actix, Tokio and basic Rust examples.

Signed-off-by: Felipe Huici <[email protected]>
  • Loading branch information
felipehuici authored and razvand committed Mar 5, 2024
1 parent a83c14d commit 4dd6409
Show file tree
Hide file tree
Showing 21 changed files with 575 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ kraft pkg ls --apps --update
| ![](./.github/icons/go.svg) | [Simple Go 1.21 HTTP Web Server with `net/http`](https://github.com/unikraft/catalog/tree/main/examples/http-go1.21) |
| ![](./.github/icons/python3.svg) | [Simple Flask 3.0 HTTP Web Server](https://github.com/unikraft/catalog/tree/main/examples/http-python3.10-flask3.0) |
| ![](./.github/icons/python3.svg) | [Simple Python 3.10 HTTP Web Server with `http.server.HTTPServer`](https://github.com/unikraft/catalog/tree/main/examples/http-python3.10) |
| ![](./.github/icons/rust-white.svg) | [Rust Actix Web Server](https://github.com/unikraft/catalog/tree/main/examples/http-rust1.75-actix-web4) |
| ![](./.github/icons/rust-white.svg) | [Rust/Rocket v0.5](https://github.com/unikraft/catalog/tree/main/examples/http-rust1.75-rocket0.5) |
| ![](./.github/icons/rust-white.svg) | [Rust/Tokio Server](https://github.com/unikraft/catalog/tree/main/examples/http-rust1.75-tokio) |
| ![](./.github/icons/rust-white.svg) | [Rust HTTP Web Server](https://github.com/unikraft/catalog/tree/main/examples/http-rust1.75) |

## Library

Expand Down
8 changes: 8 additions & 0 deletions examples/http-rust1.75-actix-web4/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "hello"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies]
actix-web = "4"
15 changes: 15 additions & 0 deletions examples/http-rust1.75-actix-web4/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM rust:1.75.0-bookworm AS build

RUN cargo new --bin app
WORKDIR /app
COPY Cargo.toml ./
COPY src ./src
RUN cargo build --release

FROM scratch

COPY --from=build /app/target/release/hello /server
COPY --from=build /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/
COPY --from=build /lib/x86_64-linux-gnu/libm.so.6 /lib/x86_64-linux-gnu/
COPY --from=build /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/
COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/
7 changes: 7 additions & 0 deletions examples/http-rust1.75-actix-web4/Kraftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spec: v0.6

runtime: base:latest

rootfs: ./Dockerfile

cmd: ["/server"]
64 changes: 64 additions & 0 deletions examples/http-rust1.75-actix-web4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Rust Actix Web Server

This directory contains an [Actix](https://actix.rs/) web server running on Unikraft.

## Set Up

To run this example, [install Unikraft's companion command-line toolchain `kraft`](https://unikraft.org/docs/cli), clone this repository and `cd` into this directory.

## Run and Use

Use `kraft` to run the image and start a Unikraft instance:

```bash
kraft run --rm -p 8080:8080 --plat qemu --arch x86_64
```

If the `--plat` argument is left out, it defaults to `qemu`.
If the `--arch` argument is left out, it defaults to your system's CPU architecture.

Once executed, it will open port `8080` and wait for connections.
To test it, you can use `curl`:

```bash
curl localhost:8080
```

You should see a "Hello, World!" message.

## Inspect and Close

To list information about the Unikraft instance, use:

```bash
kraft ps
```

```text
NAME KERNEL ARGS CREATED STATUS MEM PLAT
admiring_ndakasi oci://unikraft.org/base:latest /server 1 minute ago running 64MiB 0.0.0.0:8080->8080/tcp qemu/x86_64
```

The instance name is `nostalgic_snowflake`.
To close the Unikraft instance, close the `kraft` process (e.g., via `Ctrl+c`) or run:

```bash
kraft rm nostalgic_snowflake
```

Note that depending on how you modify this example your instance **may** need more memory to run.
To do so, use the `kraft run`'s `-M` flag, for example:

```bash
kraft run -p 8080:8080 --plat qemu --arch x86_64 -M 512M
```

## `kraft` and `sudo`

Mixing invocations of `kraft` and `sudo` can lead to unexpected behavior.
Read more about how to start `kraft` without `sudo` at [https://unikraft.org/sudoless](https://unikraft.org/sudoless).

## Learn More

- [How to run unikernels locally](https://unikraft.org/docs/cli/running)
- [Building `Dockerfile` Images with `BuildKit`](https://unikraft.org/guides/building-dockerfile-images-with-buildkit)
28 changes: 28 additions & 0 deletions examples/http-rust1.75-actix-web4/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};

#[get("/")]
async fn hello() -> impl Responder {
HttpResponse::Ok().body("Hello, World!\r\n")
}

#[post("/echo")]
async fn echo(req_body: String) -> impl Responder {
HttpResponse::Ok().body(req_body)
}

async fn manual_hello() -> impl Responder {
HttpResponse::Ok().body("Hey there!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(hello)
.service(echo)
.route("/hey", web::get().to(manual_hello))
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
8 changes: 8 additions & 0 deletions examples/http-rust1.75-rocket0.5/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "hello"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies]
rocket = "0.5.0"
17 changes: 17 additions & 0 deletions examples/http-rust1.75-rocket0.5/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM rust:1.75.0-bookworm AS build

RUN cargo new --bin app
WORKDIR /app
COPY Cargo.toml ./
COPY Rocket.toml ./
COPY src ./src
RUN cargo build --release

FROM scratch

COPY ./Rocket.toml /Rocket.toml
COPY --from=build /app/target/release/hello /server
COPY --from=build /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/
COPY --from=build /lib/x86_64-linux-gnu/libm.so.6 /lib/x86_64-linux-gnu/
COPY --from=build /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/
COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/
7 changes: 7 additions & 0 deletions examples/http-rust1.75-rocket0.5/Kraftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spec: v0.6

runtime: base:latest

rootfs: ./Dockerfile

cmd: ["/server"]
75 changes: 75 additions & 0 deletions examples/http-rust1.75-rocket0.5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Rust/Rocket v0.5

This example was derived from [Rocket's "hello" example](https://github.com/rwf2/Rocket/tree/v0.5/examples/hello).

## Set Up

To run this example, [install Unikraft's companion command-line toolchain `kraft`](https://unikraft.org/docs/cli), clone this repository and `cd` into this directory.

## Run and Use

Use `kraft` to run the image and start a Unikraft instance:

```bash
kraft run --rm -p 8080:8080 --plat qemu --arch x86_64
```

If the `--plat` argument is left out, it defaults to `qemu`.
If the `--arch` argument is left out, it defaults to your system's CPU architecture.

Once executed, it will open port `8080` and wait for connections.
To test it, you can use `curl`.
Try one of these available endpoints:

```bash
Then try visiting one of the available paths:
- https://<NAME>.<METRO>.kraft.cloud/hello/world
- https://<NAME>.<METRO>.kraft.cloud/hello/мир
- https://<NAME>.<METRO>.kraft.cloud/wave/Rocketeer/100
- https://<NAME>.<METRO>.kraft.cloud/?emoji
- https://<NAME>.<METRO>.kraft.cloud/?name=Rocketeer
- https://<NAME>.<METRO>.kraft.cloud/?lang=ру
- https://<NAME>.<METRO>.kraft.cloud/?lang=ру&emoji
- https://<NAME>.<METRO>.kraft.cloud/?emoji&lang=en
- https://<NAME>.<METRO>.kraft.cloud/?name=Rocketeer&lang=en
- https://<NAME>.<METRO>.kraft.cloud/?emoji&name=Rocketeer
- https://<NAME>.<METRO>.kraft.cloud/?name=Rocketeer&lang=en&emoji
- https://<NAME>.<METRO>.kraft.cloud/?lang=ru&emoji&name=Rocketeer
```

## Inspect and Close

To list information about the Unikraft instance, use:

```bash
kraft ps
```

```text
NAME KERNEL ARGS CREATED STATUS MEM PLAT
admiring_ndakasi oci://unikraft.org/base:latest /server 1 minute ago running 64MiB 0.0.0.0:8080->8080/tcp qemu/x86_64
```

The instance name is `nostalgic_snowflake`.
To close the Unikraft instance, close the `kraft` process (e.g., via `Ctrl+c`) or run:

```bash
kraft rm nostalgic_snowflake
```

Note that depending on how you modify this example your instance **may** need more memory to run.
To do so, use the `kraft run`'s `-M` flag, for example:

```bash
kraft run -p 8080:8080 --plat qemu --arch x86_64 -M 512M
```

## `kraft` and `sudo`

Mixing invocations of `kraft` and `sudo` can lead to unexpected behavior.
Read more about how to start `kraft` without `sudo` at [https://unikraft.org/sudoless](https://unikraft.org/sudoless).

## Learn More

- [How to run unikernels locally](https://unikraft.org/docs/cli/running)
- [Building `Dockerfile` Images with `BuildKit`](https://unikraft.org/guides/building-dockerfile-images-with-buildkit)
3 changes: 3 additions & 0 deletions examples/http-rust1.75-rocket0.5/Rocket.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[default]
address = "0.0.0.0"
port = 8080
81 changes: 81 additions & 0 deletions examples/http-rust1.75-rocket0.5/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#[macro_use] extern crate rocket;

#[cfg(test)] mod tests;

#[derive(FromFormField)]
enum Lang {
#[field(value = "en")]
English,
#[field(value = "ru")]
#[field(value = "ру")]
Russian
}

#[derive(FromForm)]
struct Options<'r> {
emoji: bool,
name: Option<&'r str>,
}

// Try visiting:
// http://127.0.0.1:8000/hello/world
#[get("/world")]
fn world() -> &'static str {
"Hello, World!"
}

// Try visiting:
// http://127.0.0.1:8000/hello/мир
#[get("/мир")]
fn mir() -> &'static str {
"Привет, мир!"
}

// Try visiting:
// http://127.0.0.1:8000/wave/Rocketeer/100
#[get("/<name>/<age>")]
fn wave(name: &str, age: u8) -> String {
format!("👋 Hello, {} year old named {}!", age, name)
}

// Note: without the `..` in `opt..`, we'd need to pass `opt.emoji`, `opt.name`.
//
// Try visiting:
// http://127.0.0.1:8000/?emoji
// http://127.0.0.1:8000/?name=Rocketeer
// http://127.0.0.1:8000/?lang=ру
// http://127.0.0.1:8000/?lang=ру&emoji
// http://127.0.0.1:8000/?emoji&lang=en
// http://127.0.0.1:8000/?name=Rocketeer&lang=en
// http://127.0.0.1:8000/?emoji&name=Rocketeer
// http://127.0.0.1:8000/?name=Rocketeer&lang=en&emoji
// http://127.0.0.1:8000/?lang=ru&emoji&name=Rocketeer
#[get("/?<lang>&<opt..>")]
fn hello(lang: Option<Lang>, opt: Options<'_>) -> String {
let mut greeting = String::new();
if opt.emoji {
greeting.push_str("👋 ");
}

match lang {
Some(Lang::Russian) => greeting.push_str("Привет"),
Some(Lang::English) => greeting.push_str("Hello"),
None => greeting.push_str("Hi"),
}

if let Some(name) = opt.name {
greeting.push_str(", ");
greeting.push_str(name);
}

greeting.push('!');
greeting
}

#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/", routes![hello])
.mount("/hello", routes![world, mir])
.mount("/wave", routes![wave])
}
8 changes: 8 additions & 0 deletions examples/http-rust1.75-tokio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "http-tokio"
version = "0.1.0"
edition = "2021"


[dependencies]
tokio = {version = "1", features = ["rt-multi-thread", "net", "time", "macros", "io-util"] }
16 changes: 16 additions & 0 deletions examples/http-rust1.75-tokio/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM rust:1.75.0-bookworm AS build

WORKDIR /src

COPY ./src /src/src
COPY ./Cargo.toml /src/Cargo.toml

RUN cargo build

FROM scratch

COPY --from=build src/target/debug/http-tokio /server
COPY --from=build /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6
COPY --from=build /lib/x86_64-linux-gnu/libm.so.6 /lib/x86_64-linux-gnu/libm.so.6
COPY --from=build /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libgcc_s.so.1
COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
7 changes: 7 additions & 0 deletions examples/http-rust1.75-tokio/Kraftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spec: v0.6

runtime: base:latest

rootfs: ./Dockerfile

cmd: ["/server"]
Loading

0 comments on commit 4dd6409

Please sign in to comment.