- Docker Desktop (or Docker Engine + Docker Compose)
-
(Optional) Copy environment variables to override defaults:
cp .env.example .env
-
Start frontend + Express backend + PostgreSQL:
docker compose up --build
This is the single command that starts the local stack.
All published ports are loopback-only (127.0.0.1) for local development.
- Frontend:
http://localhost:8080 - Backend (Express):
http://localhost:3000 - Backend health:
http://localhost:3000/health - Backend health (via frontend proxy):
http://localhost:8080/health - PostgreSQL:
localhost:5432(inside Docker network asdb:5432)
The frontend is served by nginx and API requests are proxied to the Express backend.
This Docker stack establishes the PostgreSQL database foundation:
- Frontend container builds and serves static assets
- Express backend boots and responds on
/health - PostgreSQL service starts, becomes healthy, and runs
bookrunner.sqlwhen the data volume is first initialized - Backend receives
DATABASE_URLfor future PostgreSQL-backed API work
Backend data access (auth, cart, orders) is not yet implemented and is tracked in:
- #5 (auth)
- #6 (cart)
- #7 (orders)
DATABASE_URL is wired into the backend service environment so those issues can connect immediately without further Docker changes.
Run the full stack:
docker compose up --buildExpected results:
- PostgreSQL becomes healthy (
pg_isreadypasses) - Schema tables (
users,cart_items,orders,order_items) are created frombookrunner.sql - Backend
/healthreturns200 {"status":"ok"} - Frontend is accessible at
http://localhost:8080 - Backend health is accessible at
http://localhost:3000/healthand via proxy athttp://localhost:8080/health
Note: PostgreSQL starts and initializes the schema, but backend API routes for auth/cart/orders are not yet connected. Those are implemented in #5, #6, and #7.
Schema reset: PostgreSQL init scripts only run when the data volume is empty. If
bookrunner.sqlchanges, rundocker compose down -vbefore starting the stack again to force a fresh schema initialization.
-
Stop services:
docker compose down
-
Stop and remove DB volume too:
docker compose down -v
Two workflow files drive the automation pipeline:
Triggered on every push and pull request to any branch. The test job runs first; build-backend and build-frontend both depend on test and then run in parallel:
- Backend tests – installs Node.js 20, runs
npm ciandnpm testinsidebackend/ - Build backend Docker image – builds
docker/backend/Dockerfile(no push) - Build frontend Docker image – builds
docker/frontend/Dockerfile(no push)
Frontend/Selenium checks: No Selenium test infrastructure exists in this repository yet. Frontend integration tests are deferred to issue #10 and will be added to CI once that work is complete.
Triggered on push to main and on version tags (v*). Concurrent runs on the same ref are cancelled automatically (cancel-in-progress: true).
- Backend tests – same as CI
- Build & push images to ACR – logs in to Azure Container Registry and pushes both images. Branch builds are tagged
main-<8-char SHA>; tag builds use the tag name (e.g.v1.2.3). - Deploy to staging – deploys to Azure Container Apps when the commit lands on
main - Deploy to production – deploys to Azure Container Apps when a
v*tag is pushed and the tagged commit is reachable frommain(prevents shipping code that bypassed staging)
Configure these in Settings → Secrets and variables → Actions before the CD workflow can run:
| Secret | Description |
|---|---|
ACR_LOGIN_SERVER |
ACR login server, e.g. myregistry.azurecr.io |
ACR_USERNAME |
ACR admin username (or service-principal client ID) |
ACR_PASSWORD |
ACR admin password (or service-principal client secret) |
AZURE_CREDENTIALS |
JSON service-principal credentials. Create with:az ad sp create-for-rbac --name bookrunner-cicd --role contributor --scopes /subscriptions/<SUB_ID>/resourceGroups/<RG> --json-auth |
ACA_RESOURCE_GROUP |
Azure resource group containing the Container Apps |
ACA_STAGING_BACKEND_APP |
Container App name for staging backend |
ACA_STAGING_FRONTEND_APP |
Container App name for staging frontend |
ACA_PRODUCTION_BACKEND_APP |
Container App name for production backend |
ACA_PRODUCTION_FRONTEND_APP |
Container App name for production frontend |
- Node.js v18 or later
- npm (bundled with Node.js)
cd backend
npm installcp .env.example .env
# Edit .env as needed (PORT, HOST, NODE_ENV, DATABASE_URL)npm startThe API will be available at http://localhost:3000 by default.
DATABASE_URL is available for PostgreSQL-backed endpoints, but the current backend only uses /health. Auth, cart, and order data access are tracked separately in #5, #6, and #7.
GET /health
Returns HTTP 200 with JSON:
{ "status": "ok" }npm testVerified locally with:
npm installnpm start(server booted successfully)GET /healthreturned200 {"status":"ok"}npm testpassed forGET /health