build: add shared Postgres and Valkey to compose
- postgres replaces keycloak-db and holds a keycloak and a mancala database, each with its own user, created by apps/postgres/init - valkey with an append-only file for live game state and caches - backend gets DATABASE_URL and VALKEY_URL
This commit is contained in:
parent
d0004742f5
commit
29fa443b93
17
README.md
17
README.md
@ -12,6 +12,23 @@ yarn build:packages # from the repo root
|
|||||||
|
|
||||||
After changing a package, rebuild it (or run `yarn dev` in it to rebuild on change); the apps pick up the new `dist`.
|
After changing a package, rebuild it (or run `yarn dev` in it to rebuild on change); the apps pick up the new `dist`.
|
||||||
|
|
||||||
|
Postgres (games and Keycloak), Valkey (live games and caches) and Keycloak run with Docker Compose. Create
|
||||||
|
`apps/.env` once, then start them:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apps
|
||||||
|
cat > .env <<EOF
|
||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
|
KEYCLOAK_DB_PASSWORD=keycloak
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD=admin
|
||||||
|
MANCALA_DB_PASSWORD=mancala
|
||||||
|
EOF
|
||||||
|
docker compose up -d --build postgres valkey keycloak
|
||||||
|
```
|
||||||
|
|
||||||
|
Postgres is on `localhost:5433` and Valkey on `localhost:6379`; the backend's defaults point there. Then run
|
||||||
|
`yarn dev` in `apps/backend` (port 5005) and in `apps/frontend` (port 1234).
|
||||||
|
|
||||||
Docker images for the backend and frontend are built from the repo root:
|
Docker images for the backend and frontend are built from the repo root:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@ -11,8 +11,13 @@ services:
|
|||||||
KEYCLOAK_JWKS_URL: http://keycloak:8080/realms/mancala/protocol/openid-connect/certs
|
KEYCLOAK_JWKS_URL: http://keycloak:8080/realms/mancala/protocol/openid-connect/certs
|
||||||
KEYCLOAK_CLIENT_IDS: mancala-web
|
KEYCLOAK_CLIENT_IDS: mancala-web
|
||||||
LEGACY_USERKEY_AUTH: ${LEGACY_USERKEY_AUTH:-true}
|
LEGACY_USERKEY_AUTH: ${LEGACY_USERKEY_AUTH:-true}
|
||||||
|
DATABASE_URL: postgres://mancala:${MANCALA_DB_PASSWORD}@postgres:5432/mancala
|
||||||
|
VALKEY_URL: redis://valkey:6379
|
||||||
ports:
|
ports:
|
||||||
- "5000:6000"
|
- "5000:6000"
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
- valkey
|
||||||
frontend:
|
frontend:
|
||||||
image: jhalitaksoy/mancala-frontend:latest
|
image: jhalitaksoy/mancala-frontend:latest
|
||||||
build:
|
build:
|
||||||
@ -22,16 +27,33 @@ services:
|
|||||||
KEYCLOAK_URL: ${KEYCLOAK_HOSTNAME:-http://localhost:8080}
|
KEYCLOAK_URL: ${KEYCLOAK_HOSTNAME:-http://localhost:8080}
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
keycloak-db:
|
# Shared by Keycloak and the game, each with its own database and user (see postgres/init).
|
||||||
|
postgres:
|
||||||
image: postgres:17.6
|
image: postgres:17.6
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: keycloak
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in apps/.env}
|
||||||
POSTGRES_USER: keycloak
|
KEYCLOAK_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD:?set KEYCLOAK_DB_PASSWORD in apps/.env}
|
||||||
POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD:?set KEYCLOAK_DB_PASSWORD in apps/.env}
|
MANCALA_DB_PASSWORD: ${MANCALA_DB_PASSWORD:?set MANCALA_DB_PASSWORD in apps/.env}
|
||||||
volumes:
|
volumes:
|
||||||
- keycloak-db:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
- ./postgres/init:/docker-entrypoint-initdb.d:ro
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5433:5432"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
# Live game state and caches; the append-only file keeps live games across restarts.
|
||||||
|
valkey:
|
||||||
|
image: valkey/valkey:9.1.2
|
||||||
|
command: ["valkey-server", "--appendonly", "yes"]
|
||||||
|
volumes:
|
||||||
|
- valkey-data:/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:6379:6379"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "valkey-cli", "ping"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
@ -39,7 +61,7 @@ services:
|
|||||||
image: jhalitaksoy/mancala-keycloak:latest
|
image: jhalitaksoy/mancala-keycloak:latest
|
||||||
build: ./keycloak
|
build: ./keycloak
|
||||||
environment:
|
environment:
|
||||||
KC_DB_URL: jdbc:postgresql://keycloak-db:5432/keycloak
|
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
|
||||||
KC_DB_USERNAME: keycloak
|
KC_DB_USERNAME: keycloak
|
||||||
KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
|
KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
|
||||||
# Public URL of Keycloak; https://auth.playmancala.app in production
|
# Public URL of Keycloak; https://auth.playmancala.app in production
|
||||||
@ -52,8 +74,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8080:8080"
|
- "127.0.0.1:8080:8080"
|
||||||
depends_on:
|
depends_on:
|
||||||
keycloak-db:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
keycloak-db:
|
postgres-data:
|
||||||
|
valkey-data:
|
||||||
|
|||||||
@ -38,12 +38,17 @@ console too, or delete the realm and restart Keycloak.
|
|||||||
```sh
|
```sh
|
||||||
cd apps
|
cd apps
|
||||||
cat > .env <<EOF
|
cat > .env <<EOF
|
||||||
|
POSTGRES_PASSWORD=change-me
|
||||||
KEYCLOAK_DB_PASSWORD=change-me
|
KEYCLOAK_DB_PASSWORD=change-me
|
||||||
KEYCLOAK_ADMIN_PASSWORD=change-me
|
KEYCLOAK_ADMIN_PASSWORD=change-me
|
||||||
|
MANCALA_DB_PASSWORD=change-me
|
||||||
EOF
|
EOF
|
||||||
docker compose up -d --build keycloak
|
docker compose up -d --build keycloak
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Keycloak uses the `keycloak` database of the shared `postgres` service; `apps/postgres/init` creates it the first time
|
||||||
|
the Postgres volume is initialised.
|
||||||
|
|
||||||
Keycloak is then at http://localhost:8080 and the admin console at http://localhost:8080/admin.
|
Keycloak is then at http://localhost:8080 and the admin console at http://localhost:8080/admin.
|
||||||
In production set `KEYCLOAK_HOSTNAME=https://auth.playmancala.app`; nginx proxies that host to port 8080.
|
In production set `KEYCLOAK_HOSTNAME=https://auth.playmancala.app`; nginx proxies that host to port 8080.
|
||||||
|
|
||||||
|
|||||||
15
apps/postgres/init/01-databases.sh
Executable file
15
apps/postgres/init/01-databases.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Runs once, when the Postgres data directory is created: one database and user each for Keycloak and the game.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${KEYCLOAK_DB_PASSWORD:?KEYCLOAK_DB_PASSWORD is not set}"
|
||||||
|
: "${MANCALA_DB_PASSWORD:?MANCALA_DB_PASSWORD is not set}"
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" \
|
||||||
|
-v keycloak_password="$KEYCLOAK_DB_PASSWORD" \
|
||||||
|
-v mancala_password="$MANCALA_DB_PASSWORD" <<'EOSQL'
|
||||||
|
CREATE ROLE keycloak LOGIN PASSWORD :'keycloak_password';
|
||||||
|
CREATE DATABASE keycloak OWNER keycloak;
|
||||||
|
CREATE ROLE mancala LOGIN PASSWORD :'mancala_password';
|
||||||
|
CREATE DATABASE mancala OWNER mancala;
|
||||||
|
EOSQL
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Work through the tasks in order; each ends with its tests passing and a commit. Tick a task when it is committed.
|
Work through the tasks in order; each ends with its tests passing and a commit. Tick a task when it is committed.
|
||||||
|
|
||||||
- [ ] 1. **Infrastructure**: `postgres` service with init script for the `keycloak` and `mancala` databases
|
- [x] 1. **Infrastructure**: `postgres` service with init script for the `keycloak` and `mancala` databases
|
||||||
(replacing `keycloak-db`), `valkey` service, backend `DATABASE_URL` / `VALKEY_URL`, `.env` variables, README.
|
(replacing `keycloak-db`), `valkey` service, backend `DATABASE_URL` / `VALKEY_URL`, `.env` variables, README.
|
||||||
- [ ] 2. **Core types and history helpers**: `PlayerSummary`, `MoveRecord`, summaries, `GameRecord`,
|
- [ ] 2. **Core types and history helpers**: `PlayerSummary`, `MoveRecord`, summaries, `GameRecord`,
|
||||||
`TURN_TIMEOUT_MS`, new channels, `offlineSince`; `getInitialBoard`, `getBoardAfterMove`, `describeMove`,
|
`TURN_TIMEOUT_MS`, new channels, `offlineSince`; `getInitialBoard`, `getBoardAfterMove`, `describeMove`,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user