tools/dev-deploy: long-lived dev environment behind host Caddy
A docker-compose stack that hosts postgres, redis, mailpit, backend, gateway, and an app-routing Caddy. Reachable through the host Caddy at https://www.galaxy.lan (static SPA) and https://api.galaxy.lan (REST + gRPC). Coexists with tools/local-dev/ and tools/local-ci/ by giving every name (compose project, container, network, volume) a distinct galaxy-dev-* prefix. State is persisted in named volumes; game-state lives under ${GALAXY_DEV_GAME_STATE_DIR:-$HOME/.galaxy-dev/game-state} so the default works for a non-root runner without sudo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
# Defaults for the long-lived dev stack. Copy to `.env` and edit
|
||||||
|
# per-environment overrides. Everything in this file is non-secret;
|
||||||
|
# real credentials would go through Gitea Actions secrets and never
|
||||||
|
# this file.
|
||||||
|
#
|
||||||
|
# The compose `${VAR:-default}` expansions fall back to the values
|
||||||
|
# baked into `docker-compose.yml`, so this file documents the knobs
|
||||||
|
# rather than driving them.
|
||||||
|
|
||||||
|
# Auto-provisioned sandbox bootstrap. Empty disables the bootstrap.
|
||||||
|
BACKEND_DEV_SANDBOX_EMAIL=dev@galaxy.lan
|
||||||
|
BACKEND_DEV_SANDBOX_ENGINE_IMAGE=galaxy-engine:dev
|
||||||
|
BACKEND_DEV_SANDBOX_ENGINE_VERSION=0.1.0
|
||||||
|
BACKEND_DEV_SANDBOX_PLAYER_COUNT=20
|
||||||
|
|
||||||
|
# `123456` short-circuits the email-code path for the dev account.
|
||||||
|
# Leave empty in environments where real Mailpit codes must be used.
|
||||||
|
BACKEND_AUTH_DEV_FIXED_CODE=123456
|
||||||
|
|
||||||
|
# Name of the external Docker bridge the host Caddy is attached to.
|
||||||
|
GALAXY_EDGE_NETWORK=edge
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Application-routing Caddy for the long-lived dev environment.
|
||||||
|
# Listens only on the `edge` Docker network; TLS termination and the
|
||||||
|
# real `:80`/`:443` listeners belong to the host Caddy in front of us.
|
||||||
|
#
|
||||||
|
# `/srv/galaxy-ui` is mounted from the `galaxy-dev-ui-dist` named volume,
|
||||||
|
# refreshed on every dev-deploy run.
|
||||||
|
{
|
||||||
|
auto_https off
|
||||||
|
}
|
||||||
|
|
||||||
|
:80 {
|
||||||
|
@frontend host www.galaxy.lan
|
||||||
|
handle @frontend {
|
||||||
|
root * /srv/galaxy-ui
|
||||||
|
try_files {path} /index.html
|
||||||
|
file_server
|
||||||
|
encode zstd gzip
|
||||||
|
}
|
||||||
|
|
||||||
|
@api host api.galaxy.lan
|
||||||
|
handle @api {
|
||||||
|
reverse_proxy galaxy-api:8080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Production placeholder. Mirrors `Caddyfile.dev` but uses real
|
||||||
|
# hostnames and lets Caddy auto-provision TLS certificates. Not used
|
||||||
|
# until prod-deploy plumbing exists; kept under version control so the
|
||||||
|
# dev/prod surface stays symmetric.
|
||||||
|
|
||||||
|
www.galaxy.com {
|
||||||
|
root * /srv/galaxy-ui
|
||||||
|
try_files {path} /index.html
|
||||||
|
file_server
|
||||||
|
encode zstd gzip
|
||||||
|
}
|
||||||
|
|
||||||
|
api.galaxy.com {
|
||||||
|
reverse_proxy galaxy-api:8080
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
.PHONY: help up down rebuild logs status clean-data health psql build-engine seed-ui
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
REPO_ROOT := $(realpath $(CURDIR)/../..)
|
||||||
|
ENGINE_IMAGE := galaxy-engine:dev
|
||||||
|
ENGINE_LABEL := org.opencontainers.image.title=galaxy-game-engine
|
||||||
|
# Game-state root lives under the invoking user's home by default so
|
||||||
|
# `make up` works without sudo. Override `GALAXY_DEV_GAME_STATE_DIR`
|
||||||
|
# in the environment or `.env` to relocate (e.g. /var/lib/galaxy-dev/
|
||||||
|
# game-state in a production-shaped host). The value flows through to
|
||||||
|
# both the compose bind-mount and the backend's
|
||||||
|
# `BACKEND_GAME_STATE_ROOT`.
|
||||||
|
export GALAXY_DEV_GAME_STATE_DIR ?= $(HOME)/.galaxy-dev/game-state
|
||||||
|
|
||||||
|
COMPOSE := docker compose
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Long-lived Galaxy dev environment (https://*.galaxy.lan):"
|
||||||
|
@echo " make up Build images, ensure engine image, bring stack up"
|
||||||
|
@echo " make rebuild Force rebuild of backend / gateway images and bring up"
|
||||||
|
@echo " make build-engine Build $(ENGINE_IMAGE) from game/Dockerfile (no-op if present)"
|
||||||
|
@echo " make seed-ui Build ui/frontend and load into galaxy-dev-ui-dist volume"
|
||||||
|
@echo " make down Stop containers, keep named volumes"
|
||||||
|
@echo " make logs Tail all logs"
|
||||||
|
@echo " make status docker compose ps"
|
||||||
|
@echo " make health Probe the stack through the host Caddy"
|
||||||
|
@echo " make psql Open a psql shell as galaxy@galaxy_backend"
|
||||||
|
@echo " make clean-data Stop everything and wipe named volumes + game-state"
|
||||||
|
@echo ""
|
||||||
|
@echo "Requires:"
|
||||||
|
@echo " - external Docker network '$${GALAXY_EDGE_NETWORK:-edge}'"
|
||||||
|
@echo " (docker network create edge)"
|
||||||
|
@echo " - host Caddy proxying *.galaxy.lan into that network"
|
||||||
|
@echo " - game-state dir: $(GALAXY_DEV_GAME_STATE_DIR) (auto-created)"
|
||||||
|
|
||||||
|
up: build-engine
|
||||||
|
mkdir -p "$(GALAXY_DEV_GAME_STATE_DIR)"
|
||||||
|
$(COMPOSE) up -d --wait
|
||||||
|
|
||||||
|
rebuild: build-engine
|
||||||
|
$(COMPOSE) build --no-cache galaxy-backend galaxy-api
|
||||||
|
mkdir -p "$(GALAXY_DEV_GAME_STATE_DIR)"
|
||||||
|
$(COMPOSE) up -d --wait
|
||||||
|
|
||||||
|
build-engine:
|
||||||
|
@if docker image inspect $(ENGINE_IMAGE) >/dev/null 2>&1; then \
|
||||||
|
echo "$(ENGINE_IMAGE) already built; skipping (use 'docker rmi $(ENGINE_IMAGE)' to force a rebuild)."; \
|
||||||
|
else \
|
||||||
|
echo "building $(ENGINE_IMAGE)…"; \
|
||||||
|
docker build -t $(ENGINE_IMAGE) -f $(REPO_ROOT)/game/Dockerfile $(REPO_ROOT); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the UI frontend and load the resulting build/ directory into
|
||||||
|
# the named volume Caddy serves from. Used by the dev-deploy workflow
|
||||||
|
# and by anyone bringing the stack up by hand.
|
||||||
|
seed-ui:
|
||||||
|
@if [ ! -d $(REPO_ROOT)/ui/frontend/node_modules ]; then \
|
||||||
|
echo "installing UI dependencies…"; \
|
||||||
|
(cd $(REPO_ROOT)/ui && pnpm install --frozen-lockfile); \
|
||||||
|
fi
|
||||||
|
@echo "building UI (vite build)…"
|
||||||
|
(cd $(REPO_ROOT)/ui/frontend && \
|
||||||
|
VITE_GATEWAY_BASE_URL=https://api.galaxy.lan \
|
||||||
|
VITE_GATEWAY_RESPONSE_PUBLIC_KEY=$$(cat $(REPO_ROOT)/ui/frontend/.env.development \
|
||||||
|
| sed -n 's/^VITE_GATEWAY_RESPONSE_PUBLIC_KEY=//p') \
|
||||||
|
pnpm build)
|
||||||
|
@echo "loading build/ into galaxy-dev-ui-dist volume…"
|
||||||
|
docker volume create galaxy-dev-ui-dist >/dev/null
|
||||||
|
docker run --rm \
|
||||||
|
-v galaxy-dev-ui-dist:/dst \
|
||||||
|
-v $(REPO_ROOT)/ui/frontend/build:/src:ro \
|
||||||
|
alpine sh -c 'rm -rf /dst/* /dst/.??* 2>/dev/null; cp -a /src/. /dst/'
|
||||||
|
|
||||||
|
down:
|
||||||
|
$(COMPOSE) down
|
||||||
|
|
||||||
|
logs:
|
||||||
|
$(COMPOSE) logs -f --tail=100
|
||||||
|
|
||||||
|
status:
|
||||||
|
$(COMPOSE) ps
|
||||||
|
|
||||||
|
health:
|
||||||
|
@echo "Frontend (https://www.galaxy.lan):"
|
||||||
|
@curl -sS -o /dev/null -w " HTTP %{http_code}\n" https://www.galaxy.lan/ || echo " unreachable"
|
||||||
|
@echo "API healthz (https://api.galaxy.lan/healthz):"
|
||||||
|
@curl -sS -o /dev/null -w " HTTP %{http_code}\n" https://api.galaxy.lan/healthz || echo " unreachable"
|
||||||
|
|
||||||
|
psql:
|
||||||
|
$(COMPOSE) exec galaxy-postgres psql -U galaxy -d galaxy_backend
|
||||||
|
|
||||||
|
clean-data:
|
||||||
|
@echo "Stopping containers and engines, then wiping volumes + game-state…"
|
||||||
|
@ids=$$(docker ps -aq --filter label=$(ENGINE_LABEL)); \
|
||||||
|
if [ -n "$$ids" ]; then \
|
||||||
|
echo "stopping engine containers…"; \
|
||||||
|
docker rm -f $$ids >/dev/null; \
|
||||||
|
fi
|
||||||
|
$(COMPOSE) down -v
|
||||||
|
@if [ -d "$(GALAXY_DEV_GAME_STATE_DIR)" ]; then \
|
||||||
|
echo "wiping $(GALAXY_DEV_GAME_STATE_DIR)…"; \
|
||||||
|
docker run --rm -v "$(GALAXY_DEV_GAME_STATE_DIR):/state" alpine sh -c 'rm -rf /state/*' 2>/dev/null \
|
||||||
|
|| rm -rf "$(GALAXY_DEV_GAME_STATE_DIR)"/* 2>/dev/null || true; \
|
||||||
|
fi
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
# `tools/dev-deploy/` — long-lived Galaxy dev environment
|
||||||
|
|
||||||
|
A docker-compose stack that runs the Galaxy backend, gateway, supporting
|
||||||
|
services, and a small Caddy in front of them, reachable through the host
|
||||||
|
Caddy at `https://www.galaxy.lan` and `https://api.galaxy.lan`. Used by
|
||||||
|
the `dev-deploy.yaml` Gitea Actions workflow as the canonical dev target
|
||||||
|
on every merge into the `development` branch, and runnable by hand
|
||||||
|
through this Makefile for local debugging of the deploy plumbing
|
||||||
|
itself.
|
||||||
|
|
||||||
|
This stack is **not** the developer's primary playground for UI work —
|
||||||
|
that role still belongs to [`tools/local-dev/`](../local-dev/README.md),
|
||||||
|
which is faster (Vite HMR, host-side dev server) and isolated to one
|
||||||
|
developer. The two stacks coexist on the same host because every name
|
||||||
|
is distinct:
|
||||||
|
|
||||||
|
| | `tools/local-dev/` | `tools/dev-deploy/` |
|
||||||
|
|------------------|------------------------------|-----------------------------|
|
||||||
|
| Compose project | `local-dev` | `galaxy-dev` |
|
||||||
|
| Container prefix | `galaxy-local-dev-*` | `galaxy-dev-*` |
|
||||||
|
| Network | `galaxy-local-dev-net` | `galaxy-dev-internal`, `edge` |
|
||||||
|
| Volumes | `galaxy-local-dev-*` | `galaxy-dev-*` |
|
||||||
|
| Host ports | 5433/6380/8025/8080/9090 | none (only `edge` network) |
|
||||||
|
| Game state | `/tmp/galaxy-game-state` | `/var/lib/galaxy-dev/game-state` |
|
||||||
|
| Engine image | `galaxy-engine:local-dev` | `galaxy-engine:dev` |
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
The host must already provide:
|
||||||
|
|
||||||
|
- Docker daemon reachable as the user running `make` (member of the
|
||||||
|
`docker` group, no sudo).
|
||||||
|
- An external bridge network named `edge` (or whatever
|
||||||
|
`GALAXY_EDGE_NETWORK` overrides to):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker network create edge
|
||||||
|
```
|
||||||
|
|
||||||
|
- A host Caddy listening on `:80`/`:443`, attached to the `edge`
|
||||||
|
network, and proxying `www.galaxy.lan` and `api.galaxy.lan` to
|
||||||
|
`galaxy-caddy:80`. Example fragment for the host Caddyfile:
|
||||||
|
|
||||||
|
```caddy
|
||||||
|
www.galaxy.lan, api.galaxy.lan {
|
||||||
|
tls internal
|
||||||
|
reverse_proxy galaxy-caddy:80
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Game-state directory writable by the user running `make`. Default
|
||||||
|
is `${HOME}/.galaxy-dev/game-state`; `make up` creates it on demand.
|
||||||
|
Override by exporting `GALAXY_DEV_GAME_STATE_DIR` (e.g. to
|
||||||
|
`/var/lib/galaxy-dev/game-state` once the host is provisioned for
|
||||||
|
it).
|
||||||
|
|
||||||
|
## Bring it up
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make -C tools/dev-deploy up
|
||||||
|
```
|
||||||
|
|
||||||
|
`up` (re)builds the local-dev backend and gateway images, makes sure the
|
||||||
|
engine image `galaxy-engine:dev` exists, and waits for healthchecks. It
|
||||||
|
does **not** seed the UI volume — that is normally done by CI. The first
|
||||||
|
time you run by hand:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make -C tools/dev-deploy seed-ui
|
||||||
|
make -C tools/dev-deploy up
|
||||||
|
make -C tools/dev-deploy health
|
||||||
|
```
|
||||||
|
|
||||||
|
`seed-ui` runs `pnpm build` in `ui/frontend/`, then copies the resulting
|
||||||
|
`build/` tree into the `galaxy-dev-ui-dist` volume. Subsequent CI deploys
|
||||||
|
overwrite this volume automatically.
|
||||||
|
|
||||||
|
## Daily flow
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make -C tools/dev-deploy rebuild # rebuild backend/gateway images + up
|
||||||
|
make -C tools/dev-deploy logs # tail compose logs
|
||||||
|
make -C tools/dev-deploy health # probe https://*.galaxy.lan
|
||||||
|
make -C tools/dev-deploy down # stop, keep state
|
||||||
|
```
|
||||||
|
|
||||||
|
State persists in named volumes between `up`/`down` cycles. The
|
||||||
|
`development` branch keeps the dev environment continuously usable —
|
||||||
|
games created last week survive into this week unless somebody
|
||||||
|
calls `make clean-data`.
|
||||||
|
|
||||||
|
## Logging in
|
||||||
|
|
||||||
|
The same dev-mode email-code override as `tools/local-dev/` applies:
|
||||||
|
|
||||||
|
1. Enter `dev@galaxy.lan` (or whatever `BACKEND_DEV_SANDBOX_EMAIL`
|
||||||
|
resolves to) in the login form.
|
||||||
|
2. Submit `123456` as the code if `BACKEND_AUTH_DEV_FIXED_CODE` is
|
||||||
|
non-empty. Otherwise open Mailpit at
|
||||||
|
`http://galaxy-mailpit:8025/` from inside the network or proxy it
|
||||||
|
through the host Caddy when needed.
|
||||||
|
|
||||||
|
The fixed-code override is rejected by production env loaders, so it
|
||||||
|
cannot leak into the prod environment.
|
||||||
|
|
||||||
|
## Networking
|
||||||
|
|
||||||
|
```
|
||||||
|
Browser
|
||||||
|
│ https://www.galaxy.lan, https://api.galaxy.lan
|
||||||
|
▼
|
||||||
|
host-Caddy (:80, :443, TLS, attached to `edge` network)
|
||||||
|
│ reverse_proxy *.galaxy.lan → galaxy-caddy:80
|
||||||
|
▼
|
||||||
|
galaxy-caddy (networks: edge + galaxy-dev-internal)
|
||||||
|
│ www.galaxy.lan → file_server /srv/galaxy-ui (volume galaxy-dev-ui-dist)
|
||||||
|
│ api.galaxy.lan → reverse_proxy galaxy-api:8080
|
||||||
|
▼
|
||||||
|
galaxy-dev-internal
|
||||||
|
├─ galaxy-api (gateway: :8080 REST, :9090 gRPC)
|
||||||
|
├─ galaxy-backend (backend: :8080 HTTP, :8081 gRPC push)
|
||||||
|
├─ galaxy-postgres (postgres: :5432)
|
||||||
|
├─ galaxy-redis (redis: :6379)
|
||||||
|
├─ galaxy-mailpit (mailpit: :8025 UI, :1025 SMTP)
|
||||||
|
└─ engine containers (spawned by backend on demand)
|
||||||
|
```
|
||||||
|
|
||||||
|
The compose project deliberately exposes no host ports. Diagnostics
|
||||||
|
that used to go through `localhost:8025` etc. now go through the
|
||||||
|
container network: `docker compose -f tools/dev-deploy/docker-compose.yml
|
||||||
|
exec galaxy-mailpit wget -qO- localhost:8025/messages` and similar.
|
||||||
|
|
||||||
|
## Persistent state and schema changes
|
||||||
|
|
||||||
|
The dev Postgres volume `galaxy-dev-postgres-data` survives redeploys.
|
||||||
|
Until the pre-production migration rule is lifted, every
|
||||||
|
backward-incompatible change to `backend/internal/postgres/migrations/00001_init.sql`
|
||||||
|
needs a manual wipe before the next deploy succeeds:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make -C tools/dev-deploy clean-data
|
||||||
|
make -C tools/dev-deploy up
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the same caveat as `tools/local-dev/`, just with a different
|
||||||
|
volume name.
|
||||||
|
|
||||||
|
## Make targets
|
||||||
|
|
||||||
|
```text
|
||||||
|
make up Build images, ensure engine image, bring stack up (waits for health)
|
||||||
|
make rebuild Rebuild backend / gateway images (ignores cache), then up
|
||||||
|
make seed-ui pnpm build + load build/ into galaxy-dev-ui-dist volume
|
||||||
|
make build-engine Build galaxy-engine:dev (no-op if image already present)
|
||||||
|
make down Stop containers, keep named volumes
|
||||||
|
make logs Tail compose logs
|
||||||
|
make status docker compose ps
|
||||||
|
make health curl https://www.galaxy.lan + https://api.galaxy.lan/healthz
|
||||||
|
make psql psql as galaxy@galaxy_backend
|
||||||
|
make clean-data Stop everything and wipe volumes + game-state dir
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `docker-compose.yml` — six services: postgres, redis, mailpit,
|
||||||
|
galaxy-backend, galaxy-api, galaxy-caddy. Reuses the alpine-runtime
|
||||||
|
Dockerfiles from `../local-dev/` so the backend healthcheck can run
|
||||||
|
`wget`. Reuses the dev keypair from `../local-dev/keys/`.
|
||||||
|
- `Caddyfile.dev` — the application-routing Caddy config, mounted into
|
||||||
|
`galaxy-caddy` at `/etc/caddy/Caddyfile`.
|
||||||
|
- `Caddyfile.prod` — placeholder for a future prod deployment; not used
|
||||||
|
by this compose.
|
||||||
|
- `Makefile` — wrapper over `docker compose` with helpers for engine,
|
||||||
|
UI seeding, health probes, and full wipe.
|
||||||
|
- `.env.example` — non-secret defaults for the compose `${VAR:-}`
|
||||||
|
expansions. Copy to `.env` if you want host-local overrides.
|
||||||
|
|
||||||
|
## Relationship to other infrastructure
|
||||||
|
|
||||||
|
- `tools/local-dev/` — single-developer playground, host-port mapped,
|
||||||
|
Vite dev server on the side. Recommended for active UI work.
|
||||||
|
- `tools/local-ci/` — Gitea + act runner for **fallback** workflow
|
||||||
|
testing without `gitea.lan`. Optional, not part of the per-stage CI
|
||||||
|
gate anymore.
|
||||||
|
- `.gitea/workflows/dev-deploy.yaml` — the CI side of this stack:
|
||||||
|
builds images, seeds the UI volume, runs `docker compose up -d` on
|
||||||
|
every merge into `development`. The Makefile in this directory is
|
||||||
|
what that workflow ultimately calls into.
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
# Long-lived dev environment for the Galaxy stack, deployed by the
|
||||||
|
# `dev-deploy.yaml` Gitea Actions workflow on every merge into the
|
||||||
|
# `development` branch and (optionally) by `make -C tools/dev-deploy up`
|
||||||
|
# from a developer shell on the same host.
|
||||||
|
#
|
||||||
|
# The stack is reachable from a browser only through the host Caddy on
|
||||||
|
# the machine, which terminates TLS and forwards `*.galaxy.lan` into the
|
||||||
|
# external `edge` Docker network where `galaxy-caddy` does app-routing.
|
||||||
|
# No service in this compose project binds a host port — coexistence
|
||||||
|
# with `tools/local-dev/` (which listens on localhost:5433/6380/8025/...)
|
||||||
|
# is achieved by distinct names, networks, and volumes.
|
||||||
|
#
|
||||||
|
# Browser → host-Caddy (:80/:443) → galaxy-caddy → {galaxy-api, /srv/galaxy-ui}
|
||||||
|
#
|
||||||
|
# Persistent state lives in named volumes under the `galaxy-dev-*`
|
||||||
|
# prefix; surviving redeploys across compose rebuilds.
|
||||||
|
|
||||||
|
name: galaxy-dev
|
||||||
|
|
||||||
|
services:
|
||||||
|
galaxy-postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: galaxy-dev-postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: galaxy
|
||||||
|
POSTGRES_PASSWORD: galaxy
|
||||||
|
POSTGRES_DB: galaxy_backend
|
||||||
|
volumes:
|
||||||
|
- galaxy-dev-postgres-data:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- galaxy-internal
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U galaxy -d galaxy_backend"]
|
||||||
|
interval: 3s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
start_period: 5s
|
||||||
|
|
||||||
|
galaxy-redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: galaxy-dev-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- redis-server
|
||||||
|
- --requirepass
|
||||||
|
- galaxy-dev
|
||||||
|
- --appendonly
|
||||||
|
- "no"
|
||||||
|
- --save
|
||||||
|
- ""
|
||||||
|
networks:
|
||||||
|
- galaxy-internal
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "-a", "galaxy-dev", "PING"]
|
||||||
|
interval: 3s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
start_period: 3s
|
||||||
|
|
||||||
|
galaxy-mailpit:
|
||||||
|
image: axllent/mailpit:v1.21
|
||||||
|
container_name: galaxy-dev-mailpit
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- galaxy-internal
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8025/livez"]
|
||||||
|
interval: 3s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
start_period: 3s
|
||||||
|
|
||||||
|
galaxy-backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: tools/local-dev/backend.Dockerfile
|
||||||
|
image: galaxy/backend:dev
|
||||||
|
container_name: galaxy-dev-backend
|
||||||
|
restart: unless-stopped
|
||||||
|
user: "0:0"
|
||||||
|
depends_on:
|
||||||
|
galaxy-postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
galaxy-mailpit:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
BACKEND_LOGGING_LEVEL: info
|
||||||
|
BACKEND_HTTP_LISTEN_ADDR: ":8080"
|
||||||
|
BACKEND_GRPC_PUSH_LISTEN_ADDR: ":8081"
|
||||||
|
BACKEND_POSTGRES_DSN: "postgres://galaxy:galaxy@galaxy-postgres:5432/galaxy_backend?search_path=backend&sslmode=disable"
|
||||||
|
BACKEND_SMTP_HOST: galaxy-mailpit
|
||||||
|
BACKEND_SMTP_PORT: "1025"
|
||||||
|
BACKEND_SMTP_FROM: "galaxy-backend@galaxy.lan"
|
||||||
|
BACKEND_SMTP_TLS_MODE: none
|
||||||
|
BACKEND_DOCKER_NETWORK: galaxy-dev-internal
|
||||||
|
BACKEND_GAME_STATE_ROOT: ${GALAXY_DEV_GAME_STATE_DIR}
|
||||||
|
BACKEND_GEOIP_DB_PATH: /var/lib/galaxy/geoip.mmdb
|
||||||
|
BACKEND_NOTIFICATION_ADMIN_EMAIL: admin@galaxy.lan
|
||||||
|
BACKEND_MAIL_WORKER_INTERVAL: 500ms
|
||||||
|
BACKEND_NOTIFICATION_WORKER_INTERVAL: 500ms
|
||||||
|
BACKEND_OTEL_TRACES_EXPORTER: none
|
||||||
|
BACKEND_OTEL_METRICS_EXPORTER: none
|
||||||
|
BACKEND_AUTH_DEV_FIXED_CODE: ${BACKEND_AUTH_DEV_FIXED_CODE:-}
|
||||||
|
BACKEND_DEV_SANDBOX_EMAIL: ${BACKEND_DEV_SANDBOX_EMAIL:-}
|
||||||
|
BACKEND_DEV_SANDBOX_ENGINE_IMAGE: ${BACKEND_DEV_SANDBOX_ENGINE_IMAGE:-galaxy-engine:dev}
|
||||||
|
BACKEND_DEV_SANDBOX_ENGINE_VERSION: ${BACKEND_DEV_SANDBOX_ENGINE_VERSION:-0.1.0}
|
||||||
|
BACKEND_DEV_SANDBOX_PLAYER_COUNT: ${BACKEND_DEV_SANDBOX_PLAYER_COUNT:-20}
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# Per-game state directories live under the same absolute path
|
||||||
|
# both inside the backend container and on the Docker daemon host,
|
||||||
|
# so the bind-mount source the backend hands to the daemon
|
||||||
|
# resolves correctly when spawning engine containers. The dev
|
||||||
|
# environment uses a distinct prefix from `tools/local-dev/` so
|
||||||
|
# the two stacks do not collide on the same host.
|
||||||
|
# Game-state root must resolve to the same absolute path inside
|
||||||
|
# the backend container and on the Docker daemon host, because
|
||||||
|
# backend hands that path to the daemon when it spawns engine
|
||||||
|
# containers. The Makefile exports `GALAXY_DEV_GAME_STATE_DIR`
|
||||||
|
# to `${HOME}/.galaxy-dev/game-state` by default, so a non-root
|
||||||
|
# runner user can write to it without sudo.
|
||||||
|
- type: bind
|
||||||
|
source: ${GALAXY_DEV_GAME_STATE_DIR}
|
||||||
|
target: ${GALAXY_DEV_GAME_STATE_DIR}
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- ../../pkg/geoip/test-data/test-data/GeoIP2-Country-Test.mmdb:/var/lib/galaxy/geoip.mmdb:ro
|
||||||
|
networks:
|
||||||
|
- galaxy-internal
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8080/healthz"]
|
||||||
|
interval: 3s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 60
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
galaxy-api:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: tools/local-dev/gateway.Dockerfile
|
||||||
|
image: galaxy/gateway:dev
|
||||||
|
container_name: galaxy-dev-api
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
galaxy-backend:
|
||||||
|
condition: service_healthy
|
||||||
|
galaxy-redis:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
GATEWAY_LOG_LEVEL: info
|
||||||
|
GATEWAY_PUBLIC_HTTP_ADDR: ":8080"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ADDR: ":9090"
|
||||||
|
GATEWAY_BACKEND_HTTP_URL: "http://galaxy-backend:8080"
|
||||||
|
GATEWAY_BACKEND_GRPC_PUSH_URL: "galaxy-backend:8081"
|
||||||
|
GATEWAY_BACKEND_GATEWAY_CLIENT_ID: dev-gateway-1
|
||||||
|
GATEWAY_RESPONSE_SIGNER_PRIVATE_KEY_PEM_PATH: /run/secrets/gateway-response.pem
|
||||||
|
GATEWAY_REDIS_MASTER_ADDR: "galaxy-redis:6379"
|
||||||
|
GATEWAY_REDIS_PASSWORD: galaxy-dev
|
||||||
|
# Anti-abuse defaults are looser than production: the dev
|
||||||
|
# environment is shared by a handful of trusted testers who
|
||||||
|
# frequently hammer the same identity to reproduce flows.
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_PUBLIC_AUTH_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_PUBLIC_AUTH_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_SEND_EMAIL_CODE_IDENTITY_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_SEND_EMAIL_CODE_IDENTITY_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_CONFIRM_EMAIL_CODE_IDENTITY_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_CONFIRM_EMAIL_CODE_IDENTITY_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_PUBLIC_MISC_MAX_BODY_BYTES: "131072"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_PUBLIC_MISC_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_PUBLIC_MISC_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_BROWSER_BOOTSTRAP_MAX_BODY_BYTES: "65536"
|
||||||
|
GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_BROWSER_ASSET_MAX_BODY_BYTES: "65536"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_IP_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_IP_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_SESSION_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_SESSION_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_USER_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_USER_RATE_LIMIT_BURST: "1000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_MESSAGE_CLASS_RATE_LIMIT_REQUESTS: "10000"
|
||||||
|
GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_MESSAGE_CLASS_RATE_LIMIT_BURST: "1000"
|
||||||
|
volumes:
|
||||||
|
- ../local-dev/keys/gateway-response.pem:/run/secrets/gateway-response.pem:ro
|
||||||
|
networks:
|
||||||
|
- galaxy-internal
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "-O-", "http://localhost:8080/healthz"]
|
||||||
|
interval: 3s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
start_period: 5s
|
||||||
|
|
||||||
|
galaxy-caddy:
|
||||||
|
image: caddy:2.11.2-alpine
|
||||||
|
container_name: galaxy-dev-caddy
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
galaxy-api:
|
||||||
|
condition: service_healthy
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile.dev:/etc/caddy/Caddyfile:ro
|
||||||
|
- galaxy-dev-caddy-data:/data
|
||||||
|
- galaxy-dev-ui-dist:/srv/galaxy-ui:ro
|
||||||
|
networks:
|
||||||
|
- galaxy-internal
|
||||||
|
- edge
|
||||||
|
|
||||||
|
networks:
|
||||||
|
galaxy-internal:
|
||||||
|
name: galaxy-dev-internal
|
||||||
|
driver: bridge
|
||||||
|
internal: false
|
||||||
|
edge:
|
||||||
|
name: ${GALAXY_EDGE_NETWORK:-edge}
|
||||||
|
external: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
galaxy-dev-postgres-data:
|
||||||
|
name: galaxy-dev-postgres-data
|
||||||
|
galaxy-dev-caddy-data:
|
||||||
|
name: galaxy-dev-caddy-data
|
||||||
|
galaxy-dev-ui-dist:
|
||||||
|
name: galaxy-dev-ui-dist
|
||||||
Reference in New Issue
Block a user