From a50c5091c40a49c197aa81cf8c33470f0a1c4402 Mon Sep 17 00:00:00 2001 From: Giorgio Gilestro Date: Fri, 22 May 2026 21:30:28 +0100 Subject: [PATCH] deploy: split compose into base (prod-ready) + dev override MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compose merges list-typed fields like \`ports\` by concatenation, so the previous prod overlay couldn't clear the base file's host port binding; the VPS app ended up listening on both port 80 (intranet) AND host port 8800 simultaneously. Restructured to the conventional dev/prod split: - docker-compose.yml: no host port — prod-ready by default - docker-compose.override.yml: dev-only host port binding (auto-loaded by \`docker compose up\` locally, skipped when prod uses explicit -f) - docker-compose.prod.yml: command-port 80 + intranet network only Production invocation: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 16 ++++++++++------ docker-compose.override.yml | 9 +++++++++ docker-compose.prod.yml | 3 --- docker-compose.yml | 5 +++-- 4 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 docker-compose.override.yml diff --git a/README.md b/README.md index ff29f5c..815c4fb 100644 --- a/README.md +++ b/README.md @@ -8,24 +8,28 @@ Production: The Python package is still named `cassandra` and several internal identifiers (cookie names, advisory-lock keys, `CASSANDRA_TOKEN` env var, CSS filename) keep the legacy name on purpose — renaming them would invalidate live sessions / locks / configs for no user benefit. See `app/branding.py` for the brand single-source-of-truth. -## Quick start +## Quick start (local dev) ```bash cp .env.example .env # fill in API keys; set CASSANDRA_TOKEN if exposing docker compose up --build # db + app + scheduler + daily backup sidecar -open http://localhost:8000/ +open http://localhost:8000/ # or whichever CASSANDRA_PORT you set ``` -## Production (VPS) +`docker-compose.override.yml` is auto-loaded and adds the host port +binding so the app is reachable on `localhost`. -Apply the prod overlay so the app has no host port binding and joins the -existing `intranet` Docker network (where Nginx Proxy Manager lives): +## Production (VPS, NPM-fronted) + +Always invoke with **explicit -f flags** — that way the dev override is +skipped and the prod overlay (no host port, joins the external +`intranet` Docker network, uvicorn on port 80) is applied: ```bash docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build ``` -Then point NPM at upstream `readmarkets-app-1:80`. +Point Nginx Proxy Manager at upstream `readmarkets-app-1:80`. ## Architecture diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..5f9c6ff --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,9 @@ +# Local-dev overlay. Auto-loaded by `docker compose up` (no -f flags needed), +# IGNORED on the VPS because prod uses explicit `-f docker-compose.yml -f +# docker-compose.prod.yml`. Keep dev-only conveniences here so the base +# `docker-compose.yml` stays prod-ready. + +services: + app: + ports: + - "${CASSANDRA_PORT:-8000}:8000" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index d9b0bd8..0623bab 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -13,9 +13,6 @@ services: app: - # Strip the host port binding from the base file: no public listener - # on the VPS, only the intranet bridge. - ports: [] command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "1"] expose: - "80" diff --git a/docker-compose.yml b/docker-compose.yml index 725b88e..3038c98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -48,8 +48,9 @@ services: condition: service_healthy redis: condition: service_healthy - ports: - - "${CASSANDRA_PORT:-8000}:8000" + # No host port by default — the local-dev override file adds one. + # See docker-compose.override.yml (dev) and docker-compose.prod.yml + # (VPS, NPM-fronted) for the two deployment modes. scheduler: build: .