Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
**/node_modules
.git
.github
.husky
payment_router
*.md
.env
**/.env
*.db
# Backend test files & artifacts — never needed inside an image
# (CI runs tests on the runner; docker-compose.test.yml builds from the
# stellar-payment-platform context, which has its own .dockerignore)
stellar-payment-platform/tests
stellar-payment-platform/*.test.js
stellar-payment-platform/test_*.txt
stellar-payment-platform/test_output.txt
stellar-payment-platform/data
stellar-payment-platform/artillery.yml
# Root-level files not referenced by any image build
docs
tmp_server.js
**/node_modules
.git
.github
.husky
payment_router
*.md
.env
**/.env
*.db

# Backend test files & artifacts — never needed inside an image
# (CI runs tests on the runner; the api-test service builds from the
# stellar-payment-platform context, which has its own .dockerignore)
stellar-payment-platform/tests
stellar-payment-platform/*.test.js
stellar-payment-platform/test_*.txt
stellar-payment-platform/test_output.txt
stellar-payment-platform/data
stellar-payment-platform/artillery.yml

# Root-level files not referenced by any image build
docs
tmp_server.js
artillery.yml
50 changes: 49 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,47 @@ The following diagram maps exactly how data flows between the user, Render, and

> These steps are split by module so you can run only what you need.

### Docker Compose profiles

Every service in `docker-compose.yml` belongs to a profile, so
`docker compose up` on its own starts nothing and you always say which stack
you want:

| Command | Starts |
| --- | --- |
| `docker compose --profile dev up` | backend, postgres, redis |
| `docker compose --profile full up` | the same, plus the built frontend on :3000 |
| `docker compose --profile test up` | the API under test on :5001 and its own database |
| `docker compose --profile integration up` | a local standalone Stellar network on :8000 |

`dev` is the everyday one. `full` adds the frontend, which is the slowest
thing in the file to build and is not needed for backend work.

The dev and test stacks use separate databases on separate host ports (5432
and 5433), so you can run both at once:

```bash
docker compose --profile dev --profile test up -d
```

`COMPOSE_PROFILES` works too, if you would rather not repeat the flag:

```bash
export COMPOSE_PROFILES=dev
docker compose up -d
```

Stop a stack with the same profile you started it with, otherwise Compose
will not know which services it is meant to remove:

```bash
docker compose --profile dev down
```

The `integration` profile pulls `stellar/quickstart`, a multi-gigabyte image
used only by the Soroban contract tests in `tests/integration/`. It is kept
out of `test` so the API tests do not drag it in.

### Frontend dashboard

```bash
Expand Down Expand Up @@ -111,7 +152,14 @@ For a typical local install that becomes, for example:
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/stellar_tags?schema=public"
```

The quickest way to get a local database is Docker:
The quickest way to get a local database is the dev profile, which also
brings up Redis:

```bash
docker compose --profile dev up -d postgres redis
```

Or a single container, if you want nothing else:

```bash
docker run --name stellar-postgres -e POSTGRES_PASSWORD=postgres \
Expand Down
64 changes: 0 additions & 64 deletions docker-compose.test.yml

This file was deleted.

210 changes: 146 additions & 64 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,64 +1,146 @@
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: stellar_tags
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5

redis:
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5

backend:
build:
context: .
dockerfile: Dockerfile
target: backend
ports:
- "5000:5000"
environment:
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/stellar_tags?schema=public
REDIS_URL: redis://redis:6379
PORT: "5000"
LOG_DIR: /app/logs
volumes:
# Keep rotated logs across container restarts. The transports cap the
# volume's growth by rotating daily / at 20MB and pruning old archives.
- backendlogs:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy

frontend:
build:
context: .
dockerfile: Dockerfile
target: frontend
args:
VITE_API_BASE: http://localhost:5000
ports:
- "3000:80"
depends_on:
- backend

volumes:
pgdata:
backendlogs:
# Every service belongs to a profile, so `docker compose up` on its own starts
# nothing and you always say which stack you want:
#
# docker compose --profile dev up backend + postgres + redis
# docker compose --profile full up the same, plus the built frontend
# docker compose --profile test up API under test + its own database
# docker compose --profile integration up local standalone Stellar network
#
# dev and test use separate databases on separate host ports, so both can run
# at once without colliding.

services:
# ── dev ────────────────────────────────────────────────────────────────────
postgres:
profiles: ["dev", "full"]
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: stellar_tags
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5

redis:
profiles: ["dev", "full"]
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5

backend:
profiles: ["dev", "full"]
build:
context: .
dockerfile: Dockerfile
target: backend
ports:
- "5000:5000"
environment:
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/stellar_tags?schema=public
REDIS_URL: redis://redis:6379
PORT: "5000"
LOG_DIR: /app/logs
volumes:
# Keep rotated logs across container restarts. The transports cap the
# volume's growth by rotating daily / at 20MB and pruning old archives.
- backendlogs:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy

# Only in full, not dev: the Vite build is the slowest thing here and backend
# work does not need it. full is dev plus this.
frontend:
profiles: ["full"]
build:
context: .
dockerfile: Dockerfile
target: frontend
args:
VITE_API_BASE: http://localhost:5000
ports:
- "3000:80"
depends_on:
- backend

# ── test ───────────────────────────────────────────────────────────────────
postgres-test:
profiles: ["test"]
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: stellar_tags_test
# 5433 on the host so a dev postgres can stay up on 5432.
ports:
- "5433:5432"
# No volume: a test database should start empty every time.
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5

api-test:
profiles: ["test"]
build:
context: ./stellar-payment-platform
dockerfile: Dockerfile.test
environment:
PORT: "5001"
DATABASE_URL: postgresql://postgres:postgres@postgres-test:5432/stellar_tags_test?schema=public
ports:
- "5001:5001"
depends_on:
postgres-test:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:5001/health"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s

# ── integration ────────────────────────────────────────────────────────────
# Standalone Stellar network (Soroban-enabled) used by the contract
# integration tests. Exposes both the Horizon REST API (8000) and the
# Soroban RPC endpoint (8000/rpc) so the Rust SDK can submit real
# transactions against a local network. Kept out of the test profile
# because it pulls a multi-gigabyte image the API tests never touch.
stellar-standalone:
profiles: ["integration"]
image: stellar/quickstart:latest
command: [
"--standalone",
"--enable-soroban-rpc",
"--enable-core-artifacts",
"--local",
]
environment:
ENABLE_LOGS: "true"
ports:
- "8000:8000"
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8000/"]
interval: 5s
timeout: 5s
retries: 20
start_period: 30s

volumes:
pgdata:
backendlogs:
Loading
Loading