chore(deploy): pull image from Gitea registry + manual buildx push flow
This commit is contained in:
129
DEPLOY.md
129
DEPLOY.md
@@ -1,90 +1,103 @@
|
|||||||
# Deploy to Dockge (fastest path: build on the host)
|
# Deploy to Dockge via the Gitea container registry
|
||||||
|
|
||||||
This is the quickest way to get Flashcard running on your Proxmox + Dockge setup.
|
Flashcard ships as one container (API + built frontend). You build the image once,
|
||||||
Source comes from Gitea; Dockge builds the image locally and runs it. No container
|
push it to your Gitea registry, and Dockge pulls it — same pattern as your
|
||||||
registry, no Gitea Actions, no `docker login` required.
|
`questionnaire` stack.
|
||||||
|
|
||||||
Repo: `https://gitea.hausmans.cloud/bert.hausmans/flashcards`
|
- Gitea repo: `https://gitea.hausmans.cloud/bert.hausmans/flashcards`
|
||||||
|
- Registry image: `10.0.10.205:3000/bert.hausmans/flashcards:latest`
|
||||||
|
|
||||||
## What gets deployed
|
## One-time prerequisites (on this Mac)
|
||||||
|
|
||||||
One container (`flashcard`) serving the API **and** the built frontend. It listens
|
The registry is plain HTTP on an IP, so Docker must trust it. In **Docker Desktop →
|
||||||
on port `3000` inside the container, mapped to **`4000` on the Dockge host**
|
Settings → Docker Engine**, add `10.0.10.205:3000` to `insecure-registries`:
|
||||||
(`4000:3000` in `compose.yaml`). A persistent named volume (`flashcard-data`) holds
|
|
||||||
the SQLite database.
|
|
||||||
Migrations run automatically on every container start.
|
|
||||||
|
|
||||||
## Step 1 — push the code to Gitea (from your dev machine)
|
```json
|
||||||
|
{
|
||||||
```bash
|
"insecure-registries": ["10.0.10.205:3000"]
|
||||||
cd /Users/berthausmans/Documents/Development/flashcard
|
}
|
||||||
git remote add origin https://gitea.hausmans.cloud/bert.hausmans/flashcards.git # first time only
|
|
||||||
git push -u origin master
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 2 — put the stack on the Dockge host
|
Apply & restart Docker. Then log in to the registry (use your Gitea username and a
|
||||||
|
Gitea access token or password — run it yourself so the prompt works):
|
||||||
|
|
||||||
SSH into the host running Dockge. Dockge keeps stacks in `/opt/stacks` by default.
|
```
|
||||||
|
! docker login 10.0.10.205:3000
|
||||||
```bash
|
|
||||||
cd /opt/stacks
|
|
||||||
git clone https://gitea.hausmans.cloud/bert.hausmans/flashcards.git flashcard
|
|
||||||
```
|
```
|
||||||
|
|
||||||
A "flashcard" stack now appears in the Dockge UI (it reads `compose.yaml`).
|
(The Dockge host already trusts this registry since `questionnaire` pulls from it.)
|
||||||
|
|
||||||
## Step 3 — configure environment in Dockge
|
## Step 1 — build for amd64 and push
|
||||||
|
|
||||||
Open the **flashcard** stack in Dockge and edit the `environment:` block:
|
Your Mac is arm64 but the Proxmox host is amd64, so build with `--platform
|
||||||
|
linux/amd64`. From the repo root:
|
||||||
|
|
||||||
- `APP_URL` → how you reach the app, e.g. `http://<dockge-host-ip>:4000`
|
```bash
|
||||||
(this is what verification/reset/invite e-mail links use — get it right).
|
docker buildx build --platform linux/amd64 \
|
||||||
- `COOKIE_SECURE` → leave `"false"` for now (plain HTTP). Flip to `"true"` only
|
-t 10.0.10.205:3000/bert.hausmans/flashcards:latest \
|
||||||
after you put the app behind HTTPS.
|
--push .
|
||||||
- SMTP (Amazon SES) → fill in `SMTP_HOST` (e.g. `email-smtp.eu-west-1.amazonaws.com`),
|
```
|
||||||
`SMTP_USER`, `SMTP_PASS`, and `SMTP_FROM`. **Optional for first boot** — see Step 5.
|
|
||||||
|
|
||||||
## Step 4 — deploy
|
That builds the image and pushes it straight to the Gitea registry.
|
||||||
|
|
||||||
Click **Deploy** (Dockge runs `docker compose up -d --build`). First build takes a
|
## Step 2 — create the Dockge stack
|
||||||
few minutes (installs deps, builds the frontend, compiles better-sqlite3). When it's
|
|
||||||
up, open `http://<dockge-host-ip>:4000`.
|
|
||||||
|
|
||||||
## Step 5 — create the first account (becomes sysadmin)
|
In Dockge, **+ Compose** → name it `flashcard`, and paste the contents of
|
||||||
|
`compose.yaml` from this repo (or copy the file into the stack directory). Then edit
|
||||||
|
the `environment:` block:
|
||||||
|
|
||||||
Go to `/register` and sign up. The **first registered user is automatically the
|
- `APP_URL` → how users reach the app, e.g. `http://10.0.10.205:4000`
|
||||||
|
(used in verification / reset / invite e-mail links — get it right).
|
||||||
|
- `COOKIE_SECURE` → leave `false` over plain HTTP; set `true` only behind HTTPS.
|
||||||
|
- SMTP (Amazon SES) → fill in `SMTP_HOST` / `SMTP_USER` / `SMTP_PASS` / `SMTP_FROM`,
|
||||||
|
**or** leave `SMTP_HOST` empty for the first boot (see Step 4).
|
||||||
|
|
||||||
|
The stack maps host **4000 → container 4000** and persists the SQLite DB in the
|
||||||
|
`flashcard-data` volume.
|
||||||
|
|
||||||
|
## Step 3 — deploy
|
||||||
|
|
||||||
|
Click **Deploy**. Dockge pulls the image and starts it. Open
|
||||||
|
`http://10.0.10.205:4000`. Migrations run automatically on container start.
|
||||||
|
|
||||||
|
## Step 4 — create the first account (becomes sysadmin)
|
||||||
|
|
||||||
|
Go to `/register` and sign up — the **first registered user is automatically the
|
||||||
sysadmin**.
|
sysadmin**.
|
||||||
|
|
||||||
- If SES is configured: click the verification link in your inbox.
|
- SES configured → click the verification link in your inbox.
|
||||||
- If you left SMTP empty: grab the verification link from the container logs —
|
- SMTP left empty → open the stack's **Logs** in Dockge and copy the
|
||||||
in Dockge open the flashcard stack → Logs, and copy the
|
`…/verify-email?token=…` link printed by the stub mailer.
|
||||||
`…/verify-email?token=…` URL printed by the stub mailer.
|
|
||||||
|
|
||||||
Then log in. Done.
|
Then log in. Done.
|
||||||
|
|
||||||
## Updating later
|
## Updating later
|
||||||
|
|
||||||
|
Rebuild & push the new image, then redeploy in Dockge:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /opt/stacks/flashcard
|
docker buildx build --platform linux/amd64 \
|
||||||
git pull
|
-t 10.0.10.205:3000/bert.hausmans/flashcards:latest --push .
|
||||||
```
|
```
|
||||||
|
|
||||||
Then in Dockge click **Deploy** again (rebuilds + restarts). The `flashcard-data`
|
In Dockge: open the **flashcard** stack → **Pull** (fetches the new image) →
|
||||||
volume — and therefore all lessons, cards and accounts — persists across redeploys.
|
**Deploy**. The `flashcard-data` volume — and all lessons, cards and accounts —
|
||||||
|
survives redeploys.
|
||||||
|
|
||||||
|
> Tip: for safe rollbacks, also tag a version alongside `latest`, e.g.
|
||||||
|
> `-t 10.0.10.205:3000/bert.hausmans/flashcards:2026-05-21 -t 10.0.10.205:3000/bert.hausmans/flashcards:latest`.
|
||||||
|
|
||||||
## Notes & gotchas
|
## Notes & gotchas
|
||||||
|
|
||||||
- **Data safety:** everything lives in the `flashcard-data` Docker volume. Don't
|
- **Data lives in the `flashcard-data` volume** — don't delete it; back up
|
||||||
delete it. Back it up by copying `/data/flashcard.db` out of the container/volume.
|
`/app/data/flashcard.db`.
|
||||||
- **Secure cookies need HTTPS.** With `COOKIE_SECURE=true` over plain HTTP the
|
- **Secure cookies need HTTPS.** Over plain HTTP keep `COOKIE_SECURE=false`,
|
||||||
browser silently discards the login cookie. Keep it `false` until you have TLS.
|
otherwise the browser drops the login cookie and sign-in silently fails.
|
||||||
- **Mailpit** (`docker-compose.yml`) is dev-only and is ignored here — Dockge uses
|
- **Mailpit** (`docker-compose.yml`) is dev-only and unrelated to this deploy.
|
||||||
`compose.yaml`.
|
- The backend runs via `tsx` and applies migrations on boot
|
||||||
- The backend runs via `tsx` (TypeScript runtime), matching dev. Migrations are
|
(`docker-entrypoint.sh`).
|
||||||
applied automatically by `docker-entrypoint.sh` before the server starts.
|
|
||||||
|
|
||||||
## Next step (optional, when you have time)
|
## Optional: automate with Gitea Actions
|
||||||
|
|
||||||
Move to the Gitea container registry + Gitea Actions so Dockge pulls a pre-built
|
If you later register a Gitea `act_runner`, I can add a `.gitea/workflows/build.yml`
|
||||||
image instead of building on the host. Ask and I'll add a `.gitea/workflows/build.yml`
|
that builds and pushes on every push to `master`, so you skip the manual buildx step.
|
||||||
plus a registry-based `compose.yaml`.
|
|
||||||
|
|||||||
58
compose.yaml
58
compose.yaml
@@ -1,43 +1,37 @@
|
|||||||
# Production stack for Dockge — builds the image on the host from this repo.
|
# Production stack for Dockge — pulls a pre-built image from the Gitea registry.
|
||||||
# Dockge prefers compose.yaml, so this file is used instead of the dev
|
# (Build + push the image first; see DEPLOY.md.)
|
||||||
# docker-compose.yml (which only runs Mailpit for local development).
|
|
||||||
services:
|
services:
|
||||||
flashcard:
|
flashcard:
|
||||||
build:
|
image: 10.0.10.205:3000/bert.hausmans/flashcards:latest
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
image: flashcard:local
|
|
||||||
container_name: flashcard
|
container_name: flashcard
|
||||||
restart: unless-stopped
|
|
||||||
# host:container — exposed on 4000 on the Dockge host, app listens on 3000 inside.
|
|
||||||
ports:
|
ports:
|
||||||
- "4000:3000"
|
- 4000:4000
|
||||||
volumes:
|
|
||||||
- flashcard-data:/data
|
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
- NODE_ENV=production
|
||||||
PORT: "3000"
|
- PORT=4000
|
||||||
DB_PATH: /data/flashcard.db
|
- DB_PATH=/app/data/flashcard.db
|
||||||
|
|
||||||
# URL where users reach the app. Used in verification / reset / invite emails.
|
# URL where users reach the app. Used in verification / reset / invite emails.
|
||||||
# CHANGE THIS to your real address, e.g. http://192.168.1.50:4000
|
# CHANGE THIS to your real address, e.g. http://10.0.10.205:4000
|
||||||
# or https://flashcards.hausmans.cloud once behind a reverse proxy.
|
- APP_URL=http://CHANGE-ME:4000
|
||||||
APP_URL: "http://CHANGE-ME:4000"
|
|
||||||
|
|
||||||
# Cookie security. Keep "false" when serving over plain HTTP — otherwise the
|
# Keep "false" over plain HTTP (otherwise the browser drops the login
|
||||||
# browser drops the session cookie and login silently fails. Set to "true"
|
# cookie). Set "true" only once behind an HTTPS reverse proxy.
|
||||||
# only once the app is served over HTTPS (reverse proxy with TLS).
|
- COOKIE_SECURE=false
|
||||||
COOKIE_SECURE: "false"
|
|
||||||
|
|
||||||
# SMTP (Amazon SES). Leave SMTP_HOST empty to fall back to a stub mailer that
|
|
||||||
# prints verification/reset links to the container logs — handy for the very
|
|
||||||
# first sysadmin signup before SES is wired up.
|
|
||||||
SMTP_HOST: ""
|
|
||||||
SMTP_PORT: "587"
|
|
||||||
SMTP_SECURE: "false"
|
|
||||||
SMTP_USER: ""
|
|
||||||
SMTP_PASS: ""
|
|
||||||
SMTP_FROM: "Flashcard <noreply@hausmans.cloud>"
|
|
||||||
|
|
||||||
|
# SMTP (Amazon SES). Leave SMTP_HOST empty to fall back to a stub mailer
|
||||||
|
# that prints verification/reset links to the container logs (handy for the
|
||||||
|
# first sysadmin signup before SES is wired up).
|
||||||
|
- SMTP_HOST=
|
||||||
|
- SMTP_PORT=587
|
||||||
|
- SMTP_SECURE=false
|
||||||
|
- SMTP_USER=
|
||||||
|
- SMTP_PASS=
|
||||||
|
- SMTP_FROM=Flashcard <noreply@hausmans.cloud>
|
||||||
|
volumes:
|
||||||
|
- flashcard-data:/app/data
|
||||||
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
flashcard-data:
|
flashcard-data:
|
||||||
|
driver: local
|
||||||
|
networks: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user