From 5ddb56ef971ec9d9a477c69a82088d03d5b8545e Mon Sep 17 00:00:00 2001 From: space Date: Sat, 1 Aug 2026 00:43:35 +0200 Subject: [PATCH] build: add a compose file that builds the image locally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docker-compose.yml pulls registry.reversed.dev. This variant builds from the checkout instead and needs no .env — every variable falls back to a working localhost default, so the stack comes up ready to register the first admin. Also exposes Postgres on 5434 (clear of the dev database on 5433) and adds a backend healthcheck so `depends_on` ordering is meaningful. Co-Authored-By: Claude Opus 5 --- README.md | 23 +++++++++++- docker-compose.local.yml | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 docker-compose.local.yml diff --git a/README.md b/README.md index ad6dee5..9a85b11 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,8 @@ Backend/ migrations/ UI/ React + Tailwind frontend (Vite), builds to UI/build/ Dockerfile multi-stage build (UI then backend) -docker-compose.yml backend + Postgres +docker-compose.yml backend (pre-built image) + Postgres +docker-compose.local.yml same stack, built from this checkout example.env .gitea/workflows/deploy.yml ``` @@ -155,6 +156,26 @@ docker compose up -d # Open http://localhost:5000 — the first account to register becomes admin. ``` +### Building the image locally + +To run from this checkout instead of the pre-built image — no `.env` needed, every +variable falls back to a working localhost default: + +```bash +docker compose -f docker-compose.local.yml up -d --build +``` + +BuildKit builds both Dockerfile stages in parallel, which can exceed Docker +Desktop's memory limit during `pnpm install`. If the build fails with "cannot +allocate memory", warm the first stage on its own and retry: + +```bash +docker build --target build -t patchpass-build . +``` + +> The local compose file ships a placeholder `INSTANCE_SECRET`. Override it before +> using the instance for anything real. + --- ## Development setup diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..14e8eb5 --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,81 @@ +# Local / self-hosted stack — builds the image from this checkout instead of +# pulling registry.reversed.dev. No .env file required: every variable has a +# working localhost default below, so this comes up ready to set up. +# +# docker compose -f docker-compose.local.yml up -d --build +# +# Then open http://localhost:5000 and register — the first account becomes ADMIN. +# +# Note: BuildKit builds the `build` and `runtime` stages in parallel, which can +# exhaust Docker Desktop's memory limit during pnpm install. If `--build` fails +# with "cannot allocate memory", warm the first stage on its own and retry: +# +# docker build --target build -t patchpass-build . +# docker compose -f docker-compose.local.yml up -d --build + +services: + backend: + build: + context: . + dockerfile: Dockerfile + target: runtime + image: patchpass/core:local + restart: unless-stopped + ports: + - "${PORT:-5000}:${PORT:-5000}" + environment: + NODE_ENV: production + TZ: ${TZ:-Europe/Berlin} + PORT: ${PORT:-5000} + + DATABASE_URL: postgresql://patchpass:patchpass@database:5432/patchpass + + # Cookie scope + public URLs. Change these when you expose the instance + # on a real hostname or a LAN IP. + DOMAIN: ${DOMAIN:-localhost} + UI_URL: ${UI_URL:-http://localhost:5000} + REACT_APP_API_URL: ${REACT_APP_API_URL:-http://localhost:5000} + CORS_URLS: ${CORS_URLS:-http://localhost:5000,http://localhost:3000} + + # Signs approval receipts (HMAC-SHA256) and hashes sessions. + # DEV DEFAULT — override with a real 32-byte hex secret for anything + # beyond local testing: openssl rand -hex 32 + INSTANCE_SECRET: ${INSTANCE_SECRET:-0000000000000000000000000000000000000000000000000000000000000000} + + RATELIMIT: ${RATELIMIT:-1000} + LOG_LEVEL: ${LOG_LEVEL:-info} + REQUEST_DEBUGGING: ${REQUEST_DEBUGGING:-false} + RESPONSE_DEBUGGING: ${RESPONSE_DEBUGGING:-false} + depends_on: + database: + condition: service_healthy + healthcheck: + test: + - CMD-SHELL + - node -e "fetch('http://127.0.0.1:'+(process.env.PORT||5000)+'/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" + interval: 10s + timeout: 5s + retries: 10 + start_period: 40s + + database: + image: postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_USER: patchpass + POSTGRES_PASSWORD: patchpass + POSTGRES_DB: patchpass + # Exposed so you can point Prisma Studio or psql at it. Host port 5434 keeps + # it clear of the dev database on 5433. + ports: + - "${DB_PORT:-5434}:5432" + volumes: + - patchpass_local_db:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U patchpass -d patchpass"] + interval: 5s + timeout: 5s + retries: 10 + +volumes: + patchpass_local_db: