Day-2 operations: deploy, data persistence, proxying, backups, updates, maintenance. Prerequisites and env vars are in installation; adding watches and configuring alerts is in setup.
StockTrack is two containers behind your own reverse proxy.
docker compose up -d --buildThis builds both images and starts them. The UI is published on the host at
http://localhost:${FRONTEND_PORT:-9181}; the UI container proxies /api to
the backend on the internal compose network, so the backend does not need to
be published. The backend's 9180:9180 host map in compose.yaml is optional
(debug only) — comment it out if you don't need it.
Point the Docker CLI at the remote daemon with a context — the images build locally and ship to the remote daemon, same command:
docker context create docker-host --docker "host=ssh://user@docker-host"
docker --context docker-host compose up -d --buildThe compose file mounts a named volume for the data directory:
volumes:
- stocktrack-data:/dataEverything that must survive a redeploy lives under /data — the SQLite
database (stocktrack.db). The containers are otherwise disposable.
Terminate TLS at your proxy and point it at
http://<docker-host>:${FRONTEND_PORT:-9181}. The UI container is the only one
that needs to be reachable; it proxies /api internally.
Back up the named volume — it holds the database.
# stop writes for a consistent copy (optional but safer)
docker --context docker-host compose stop
docker run --rm -v stocktrack-data:/data -v "$PWD":/backup alpine \
tar czf /backup/stocktrack-$(date +%F).tgz -C /data .
docker --context docker-host compose startRestore by stopping the containers, extracting the tarball back into the
volume, and starting again. To inspect the DB without disturbing the app, copy
stocktrack.db out and open it read-only rather than querying the live file.
git pull
docker compose up -d --build--build rebuilds both images; the React build runs inside the UI image, so
frontend changes ship automatically. The schema is created additively on
startup (Base.metadata.create_all) — no manual migration step. Settings you
changed in the UI live in the database (the named volume) and are preserved
across redeploys; SEED_* env values only apply on the first boot of a fresh
database.
Force a poll of a single watch (bypassing the schedule) from the Dashboard ("Check now"), or via the API:
# check watch 1 now; ?notify=true also pushes a Gotify status summary
curl -X POST "http://<docker-host>:${FRONTEND_PORT:-9181}/api/watches/1/check?notify=true"notify=false (the default) checks silently and still fires the normal
transition alerts; notify=true additionally pushes a one-shot status summary
of every product under the watch.
- Container health — the backend
HEALTHCHECKhitsGET /api/health; the UI container waits for the API to be healthy before starting. - Scrape health — each watch tracks
consecutive_failures/last_error. AfterFAILURE_ALERT_AFTER(default 6) consecutive failures a single Gotify warning is sent (not one per tick), and a recovery notice when reading resumes. This surfaces a broken parser or a blocked fetch without alert spam.
docker compose logs -f stocktrack-api # poll results, transition counts, errors
docker compose logs -f stocktrack-ui # nginx access/errorEach poll tick logs a per-watch summary like
{"parsed": N, "early": x, "public": y, "oos": z}.