Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/bug_fix_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- [ ] clear title
- [ ] docs/README updated
- [ ] no secrets/large temp files

## Bug(s)

## Changes

## Testing
13 changes: 13 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/feature_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- [ ] clear title
- [ ] docs/README updated
- [ ] no secrets/large temp files

## Goals

## Description
Summary...
New Dependencies...

## Changes

## Testing
4 changes: 4 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Please go to the `Preview` tab and select the appropriate sub-template:

* [Bug Fixes](?expand=1&template=bug_fix_template.md)
* [Features](?expand=1&template=feature_template.md)
23 changes: 23 additions & 0 deletions .github/workflows/github-actions-demo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push, workflow_dispatch]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- name: SYSTEM INFO
run: |
echo "OS ${{ runner.os }}"
echo "Arch ${{ runner.arch }}"
echo "Details: "
cat /etc/os-release
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v5
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
31 changes: 31 additions & 0 deletions labs/lab12/config.toml.backup
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2018-2022 Docker Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

disabled_plugins = ["cri"]

#root = "/var/lib/containerd"
#state = "/run/containerd"
#subreaper = true
#oom_score = 0

#[grpc]
# address = "/run/containerd/containerd.sock"
# uid = 0
# gid = 0

#[debug]
# address = "/run/containerd/debug.sock"
# uid = 0
# gid = 0
# level = "info"
Binary file added labs/lab12/containerd-shim-wasmtime-v1
Binary file not shown.
Binary file added labs/lab12/main.wasm
Binary file not shown.
Binary file added labs/lab12/moscow-time-traditional
Binary file not shown.
Binary file added labs/lab12/moscow-time-wasm.oci
Binary file not shown.
Binary file added labs/resources/12/image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image-9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added labs/resources/12/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
132 changes: 132 additions & 0 deletions labs/submission12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Lab 12 — WebAssembly Containers vs Traditional Containers
### Task 1 — Create the Moscow Time Application
##### CLI output
```bash
MODE=once go run main.go
```

![modeOnce](resources/12/image.png)

##### How it works in 3 contexts
- `isWagi()` function detects if running under Spin by checking for `REQUEST_METHOD` env var
- `runWagiOnce()` handles a single HTTP request by printing headers and body to STDOUT (CGI/WAGI style)
- Falls back to standard `net/http` server if not in CLI or WAGI mode

### Task 2 — Build Traditional Docker Container
##### Binary size
```bash
ls -lh moscow-time-traditional
```

![traditionalBinSize](resources/12/image-1.png)

##### Image size
```bash
docker image inspect moscow-time-traditional --format '{{.Size}}' | \
awk '{print $1/1024/1024 " MB"}'
```
![traditionalImgSize](resources/12/image-3.png)

##### Startup time
```bash
for i in {1..5}; do
/usr/bin/time -f "%e" docker run --rm -e MODE=once moscow-time-traditional 2>&1 | tail -n 1
done | awk '{sum+=$1; count++} END {print "Average:", sum/count, "seconds"}'
```

![alt traditionalStartupTime](resources/12/image-11.png)

##### Memory usage (server mode)
In one terminal:
```bash
docker run --rm --name test-traditional -p 8080:8080 moscow-time-traditional
```

In another:
```bash
docker stats test-traditional --no-stream
```

![traditionalMemUsage](resources/12/image-4.png)

##### Screenshot of application in browser
![appInBrowser](resources/12/image-5.png)

### Task 3 — Build WASM Container (ctr-based)
##### TinyGo version
![tinygoVersion](resources/12/image-6.png)

##### Verification of WASM binary
```bash
ls -lh main.wasm
file main.wasm
```
![wasmBinary](resources/12/image-7.png)

##### Image size
```bash
sudo ctr images ls | awk 'NR>1 && $1 ~ /moscow-time-wasm/ {print "IMAGE:", $1, "SIZE:", $4}'
```
![wasmImgSize](resources/12/image-8.png)

##### Startup time
```bash
for i in {1..5}; do
NAME="wasi-$(date +%s%N | tail -c 6)-$i"
/usr/bin/time -f "%e" sudo ctr run --rm \
--runtime io.containerd.wasmtime.v1 \
--platform wasi/wasm \
--env MODE=once \
docker.io/library/moscow-time-wasm:latest "$NAME" 2>&1 | tail -n 1
done | awk '{sum+=$1; n++} END{printf("Average: %.4f seconds\n", sum/n)}'
```

![wasmStartupTime](resources/12/image-9.png)

##### Confirmation of using ctr for WASM execution
![wasmConfirm](resources/12/image-10.png)
- Note: used same source code as traditional build

##### Server Mode Limitation
Plain WASI (Preview1) modules do not support TCP sockets. Server mode under ctr is **not supported** for the standard `main.wasm` just built, because WASI Preview1 lacks networking capabilities.
- Note: server mode can be demonstrated via Spin using the same main.wasm

##### Memory reporting
Memory reporting is **N/A via ctr**.
WASM runs in a sandboxed runtime with **different resource accounting mechanisms** than traditional Linux containers.
The wasmtime runtime manages WASM memory internally, and traditional container metrics (cgroups) don't apply.

### Task 4 — Performance Comparison & Analysis
#### Comprehensive comparison table

| Metric | Traditional Container | WASM Container | Improvement | Notes |
|--------|----------------------|----------------|-------------|-------|
| **Binary Size** | 4.5 MB | 2.4 MB | 46.67% smaller | From `ls -lh` |
| **Image Size** | 1.9772 MiB | 0.8 MiB | 59.54% smaller | From `docker image inspect` |
| **Startup Time (CLI)** | 0.932 ms | 0.574 ms | 1.63x faster | Average of 5 runs |
| **Memory Usage** | 1.367 MiB | N/A | N/A | From `docker stats` |
| **Base Image** | scratch | scratch | Same | Both minimal |
| **Source Code** | main.go | main.go | Identical | ✅ Same file! |
| **Server Mode** | ✅ Works (net/http) | ❌ Not via ctr <br> ✅ Via Spin (WAGI) | N/A | WASI Preview1 lacks sockets; <br> Spin provides HTTP abstraction |

#### Analysis questions

Answer the following in your submission:

1. **Binary Size Comparison:**
- Why is the WASM binary so much smaller than the traditional Go binary?
- TinyGo targets constrained environments and aggressively strips unused parts of the Go runtime, GC, reflection, and large standard‑library helpers that the regular Go toolchain always links in
- What did TinyGo optimize away?
- It performed whole‑program optimization (via LLVM), dead‑code elimination, simpler runtime, and can avoid heavy packages like `fmt`

2. **Startup Performance:**
- Why does WASM start faster?
- A WASM module is just a compiled sandboxed binary loaded into an existing runtime — no OS boot, no container filesystem, no separate process
- What initialization overhead exists in traditional containers?
- A traditional container has to create a process namespace, set up cgroups, mount or prepare a filesystem layer, configure networking, and start a full user‑space runtime

3. **Use Case Decision Matrix:**
- When would you choose WASM over traditional containers?
- When needing very fast cold starts, high instance density, small binary size or network transfer, while able to live within the WASI/runtime capability surface (limited direct OS access, more constrained I/O model)
- When would you stick with traditional containers?
- When needing full Linux/OS compatibility, rich system calls, mature ecosystem or heavily dependent on the filesystem