Add SQLite persistence via Docker named volume
Tasks are now stored in SQLite (DB_PATH env var, defaults to ./tasks.db). Pre-seeding runs only when the table is empty, so upgrades preserve data. This is the v1.0.0 baseline for the persistence demo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
121
README.md
121
README.md
@@ -1,97 +1,83 @@
|
||||
# demoapp — Clouderized Demo App
|
||||
|
||||
A task manager built with Scala 3 + Thorium, used to demo the full Clouderized deployment cycle: edit config, push, rebuild, see changes live.
|
||||
A task manager built with Scala 3 + Thorium, used to demonstrate Clouderized's core value prop: **stateful app upgrades with zero data loss**.
|
||||
|
||||
Tasks are persisted in SQLite backed by a Docker named volume (`demouser-data`). Rebuilding or upgrading the container leaves all user data intact.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Access to `git.clouderized.com` (Gitea)
|
||||
- The app deployed at `demoapp.clouderized.com`
|
||||
- The app deployed at `demouser.clouderized.com`
|
||||
- VPS SSH access: `ssh -i ssh/id_rsa -p 9876 cldrzd@194.233.75.123`
|
||||
|
||||
## Running the Demo
|
||||
---
|
||||
|
||||
### 1. Show the live app
|
||||
## v1 → v2 Upgrade Demo (with data persistence)
|
||||
|
||||
Open `https://demoapp.clouderized.com` in a browser. Point out:
|
||||
This is the primary demo sequence. It shows that Clouderized can upgrade a running app without wiping user data.
|
||||
|
||||
- The **teal header** with app name and version (v1.0.0)
|
||||
- CRUD functionality — add, complete, and delete tasks
|
||||
- The `/health` endpoint returning `{"status":"ok"}`
|
||||
### 1. Deploy v1.0.0
|
||||
|
||||
### 2. Make a visible change
|
||||
|
||||
Edit `src/main/resources/site.conf`:
|
||||
|
||||
```diff
|
||||
app {
|
||||
- name = "DemoCust Tasks"
|
||||
- version = "1.0.0"
|
||||
+ name = "Clouderized Tasks"
|
||||
+ version = "1.1.0"
|
||||
theme {
|
||||
- background = "#0F766E"
|
||||
+ background = "#1E40AF"
|
||||
font = "DM Sans"
|
||||
- fontSize = "16px"
|
||||
+ fontSize = "18px"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This changes the header from **teal to blue**, bumps the version, and increases font size.
|
||||
|
||||
### 3. Push the change
|
||||
On the VPS:
|
||||
|
||||
```bash
|
||||
git add src/main/resources/site.conf
|
||||
git commit -m "Update theme to blue, bump to v1.1.0"
|
||||
git push
|
||||
cd ~/customers/demouser/demoapp && git fetch --tags && git checkout v1.0.0
|
||||
cd ~/customers/demouser && docker compose up -d --build
|
||||
```
|
||||
|
||||
### 4. Watch the rebuild
|
||||
Visit `https://demouser.clouderized.com`:
|
||||
- **Teal header**, version badge shows **v1.0.0**
|
||||
- Three pre-seeded tasks are present
|
||||
- `/health` returns `{"status":"ok"}`
|
||||
|
||||
Go to Gitea Actions at `git.clouderized.com/cldrzd/demoapp/actions` and watch the pipeline:
|
||||
### 2. Add user data
|
||||
|
||||
1. `sbt assembly` builds the fat JAR
|
||||
2. Docker builds the container image
|
||||
3. The old container is replaced with the new one
|
||||
In the browser, add 2–3 tasks and delete one of the pre-seeded tasks. This simulates real user activity before an upgrade.
|
||||
|
||||
### 5. See the result
|
||||
### 3. Upgrade to v2.0.0
|
||||
|
||||
Refresh the browser. The page now shows:
|
||||
|
||||
- **Blue header** instead of teal
|
||||
- Version **v1.1.0** in the top-right
|
||||
- Larger font size
|
||||
|
||||
### 6. Reset for the next demo
|
||||
On the VPS:
|
||||
|
||||
```bash
|
||||
git revert HEAD --no-edit
|
||||
git push
|
||||
cd ~/customers/demouser/demoapp && git checkout v2.0.0
|
||||
cd ~/customers/demouser && docker compose up -d --build
|
||||
```
|
||||
|
||||
The app rebuilds and returns to its original teal theme at v1.0.0.
|
||||
Revisit `https://demouser.clouderized.com`:
|
||||
- **Blue header**, version badge shows **v2.0.0**
|
||||
- All tasks added in step 2 are still there
|
||||
- Pre-seeded tasks are not re-added (seeding is skipped when the table is non-empty)
|
||||
|
||||
### 4. Verify persistence
|
||||
|
||||
```bash
|
||||
# On the VPS — confirm the volume exists and is mounted
|
||||
docker volume inspect demouser-data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How Persistence Works
|
||||
|
||||
| Component | Detail |
|
||||
|-----------|--------|
|
||||
| Storage | SQLite at `/data/tasks.db` inside the container |
|
||||
| Volume | Docker named volume `demouser-data` mounted at `/data` |
|
||||
| Env var | `DB_PATH=/data/tasks.db` (set in `docker-compose.yml`) |
|
||||
| Seeding | Pre-seed runs only when the `tasks` table is empty |
|
||||
|
||||
The named volume `demouser-data` survives `docker compose up --build` — data is never lost on rebuild.
|
||||
|
||||
---
|
||||
|
||||
## Config Reference
|
||||
|
||||
All visual changes are driven by `src/main/resources/site.conf`:
|
||||
|
||||
| Key | Default | What it controls |
|
||||
|-----|---------|-----------------|
|
||||
| `app.name` | `"DemoCust Tasks"` | Header title |
|
||||
| `app.version` | `"1.0.0"` | Version badge in header |
|
||||
| `app.theme.background` | `"#0F766E"` (teal) | Header and button color |
|
||||
| `app.theme.font` | `"DM Sans"` | Body font family |
|
||||
| `app.theme.fontSize` | `"16px"` | Base font size |
|
||||
|
||||
## Suggested color swaps for demos
|
||||
|
||||
| Color | Hex | Effect |
|
||||
|-------|-----|--------|
|
||||
| Teal (default) | `#0F766E` | Clouderized brand color |
|
||||
| Blue | `#1E40AF` | Obvious visual change |
|
||||
| Purple | `#7C3AED` | Another clear contrast |
|
||||
| Red | `#DC2626` | High-contrast demo |
|
||||
| Key | v1.0.0 | v2.0.0 | What it controls |
|
||||
|-----|--------|--------|-----------------|
|
||||
| `app.version` | `"1.0.0"` | `"2.0.0"` | Version badge in header |
|
||||
| `app.theme.background` | `"#0F766E"` (teal) | `"#1D4ED8"` (blue) | Header and button color |
|
||||
|
||||
## Endpoints
|
||||
|
||||
@@ -105,6 +91,5 @@ All visual changes are driven by `src/main/resources/site.conf`:
|
||||
|
||||
## Notes
|
||||
|
||||
- Task storage is **in-memory** — it resets on every redeploy, which keeps the demo clean.
|
||||
- The app runs on the **Pro tier** (2GB RAM, 2 vCPU) since JVM needs the headroom.
|
||||
- Three sample tasks are pre-seeded on startup.
|
||||
- Local dev uses `./tasks.db` (relative path) when `DB_PATH` is not set.
|
||||
|
||||
Reference in New Issue
Block a user