Docker Compose
./install.sh renders a docker-compose.yml from a template. This page documents what's in it and how to customise.
Services
The generated Compose stack has up to five services:
| Service | What it does | Required |
|---|---|---|
api | The FastAPI process (apps/api/main:app) | Yes |
web | Static React/Vite UI served by nginx | Yes |
ollama | The default serving engine | Yes (when --serving=ollama) |
postgres | Storage backend | When --storage=postgres |
phoenix | Observability sidecar | When --observability=phoenix |
Sample generated docker-compose.yml (SME tier profile):
services:
api:
image: bigwave-api:0.1.0
env_file: .env
ports:
- "${BIGWAVE_API_PORT:-8000}:8000"
volumes:
- ./logs:/srv/bigwave/logs
- ./data:/srv/bigwave/data
- ./training:/srv/bigwave/training
depends_on:
- ollama
- postgres
restart: unless-stopped
web:
image: bigwave-web:0.1.0
ports:
- "${BIGWAVE_WEB_PORT:-8080}:80"
restart: unless-stopped
ollama:
image: ollama/ollama:0.5.7
volumes:
- ./ollama:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: bigwave
POSTGRES_USER: bigwave
POSTGRES_PASSWORD: ${BIGWAVE_PG_PASSWORD}
volumes:
- ./postgres:/var/lib/postgresql/data
restart: unless-stopped
phoenix:
image: arizephoenix/phoenix:7.4.0
ports:
- "6006:6006"
restart: unless-stoppedCustomising the stack
The Compose template is at deploy/templates/docker-compose.yml.j2. The installer renders it with your selected profile + flags. Common customisations:
Pin Ollama to a specific GPU
If your host has multiple GPUs and you want Bigwave on GPU 1 only:
ollama:
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["1"]
capabilities: [gpu]Mount a host-side model cache
If you've already pulled models with a system Ollama and want to reuse the cache:
ollama:
volumes:
- /home/ubuntu/.ollama:/root/.ollamaRun behind a custom reverse proxy
Bind the API port to localhost only and front with your reverse proxy:
api:
ports:
- "127.0.0.1:8000:8000" # not 0.0.0.0Then point your nginx / Traefik / Caddy at localhost:8000.
Disable the embedded Web UI
If you're serving apps/web/dist from a different host (CDN, S3, your existing front-end stack):
# Remove the `web` service from the generated docker-compose.yml,
# or use the installer flag:
./install.sh --no-embedded-web ...Networking
By default, the Compose stack uses Docker's default bridge network. All inter-service traffic stays inside the network; the only public ports are api:8000 and web:8080 (or whatever you set with --port).
For air-gapped installs, you also want to verify outbound egress. From inside the api container:
docker compose exec api curl --max-time 5 https://api.openai.com/
# Expect: connection refused / timeout (if your firewall blocks egress)Updating
git pull
./install.sh upgradeThe installer detects the existing deploy, pulls fresh images, runs any pending Alembic migrations against the existing database, and brings the stack back up. Idempotent — safe to re-run.
To regenerate the Compose file from scratch (e.g. after switching profiles):
./install.sh --profile=SME tier ... # answers any prompts that changedLogs
docker compose logs -f api # API logs
docker compose logs -f ollama # Serving engine logs
docker compose logs -f postgres # DB logsThe api service logs are also tail-able from ./logs/inference.ndjson (structured, one JSON object per request).
Resource sizing
| Component | Reasonable defaults | Heaviest dep |
|---|---|---|
| API | 1 vCPU, 1 GB RAM | Pydantic validation, request fan-out |
| Ollama | 1 vCPU, 8+ GB RAM, 1 GPU | The model itself |
| Postgres | 1 vCPU, 2 GB RAM | Eval-report rows for large suites |
| Phoenix | 1 vCPU, 2 GB RAM | Span buffer |
For a 7B model on a single consumer GPU (RTX 4090, A6000), the Ollama service is the bottleneck at 6–10 GB VRAM. Everything else fits comfortably on a small EC2 instance type.
See also
- Deploy overview — choosing the right shape
- Configuration reference — every env var the API reads