Infrastructure
Server
Docker Services
Development (docker-compose.yml)
| Service |
Image / Build |
Host port |
Container port |
Role |
postgres |
pgvector/pgvector:pg16 |
Not exposed |
5432 |
Database |
redis |
redis:7-alpine |
Not exposed |
6379 |
Queue broker |
api |
./backend (dev target) |
127.0.0.1:8010 |
8000 |
FastAPI + uvicorn |
worker |
./backend (dev target) |
None |
— |
RQ worker |
web |
./frontend (dev target) |
5174 |
5174 |
Vite dev server |
Production (docker-compose.prod.yml)
| Service |
Image / Build |
Host port |
Notes |
postgres |
pgvector/pgvector:pg16 |
Not exposed |
restart: always, internal network |
redis |
redis:7-alpine |
Not exposed |
restart: always, internal network |
api |
./backend (prod target) |
127.0.0.1:8010 |
2 uvicorn workers, restart: always |
worker |
./backend (prod target) |
None |
rq worker --with-scheduler, restart: always |
No web container in prod — Apache serves the React SPA from the filesystem.
Docker Volumes
| Volume |
Mount point (api/worker) |
Purpose |
postgres_data |
/var/lib/postgresql/data |
PostgreSQL data directory |
redis_data |
/data |
Redis persistence |
pdf_artifacts |
/artifacts |
Generated PDF contact sheets |
./backend (bind) |
/app |
Backend source code (dev: hot reload) |
./assets (bind, ro) |
/assets |
Illustration PNGs + templates |
./rag-corpus (bind, ro) |
/rag-corpus |
RAG .docx source files |
Docker Network
In production, all services share the internal bridge network. The API is the only container with a host port binding (127.0.0.1:8010). PostgreSQL and Redis are not reachable from outside Docker.
Apache Configuration
File: deploy/apache-barclays.conf — included into the main vhost at:
/etc/apache2/sites-enabled/optical-dev.oliver.solutions.conf
The FollowSymLinks option is required — deploy.sh creates a symlink at {WEB_DIR}/illustrations → {REPO_DIR}/assets/illustrations so Apache serves PNGs directly without going through the API proxy.
Backend Dockerfile
Multi-stage build in backend/Dockerfile:
| Stage |
Base |
Purpose |
base |
python:3.12-slim |
Install OS deps (WeasyPrint, Pillow) + pip install package |
dev |
base |
Copy source; pip installs dev extras (pytest, ruff, mypy) |
prod |
base |
Copy source; production-only install |
OS deps installed: libpango, libpangocairo, libgdk-pixbuf, libcairo2, libffi-dev, libgirepository1.0-dev, shared-mime-info, fonts-liberation (required by WeasyPrint for PDF rendering).
Frontend Dockerfile
frontend/Dockerfile — dev target runs Vite dev server. Production build is done on the host by deploy.sh and static files are copied to /var/www/html/barclays-banner-builder/.
Deployment Flow (deploy.sh)
| Step |
What happens |
| 1. Preflight |
Check docker, node, npm, git |
| 2. Pull code |
git pull --ff-only origin main |
| 3. Validate .env |
Fail if OPENAI_API_KEY, POSTGRES_PASSWORD, SECRET_KEY are empty |
| 4. Build images |
Rebuild only if backend/Dockerfile or pyproject.toml changed (hash check) |
| 5. Start DB + Redis |
docker compose up -d postgres redis; wait for healthcheck |
| 6. Start API |
docker compose up -d api; 3-second startup wait |
| 7. Migrations |
alembic upgrade head inside api container |
| 8. First-run seed |
Seed admin user if users table is empty |
| 9. RAG ingest |
Embed RAG corpus if rag_chunks is empty (or --reindex) |
| 10. Icon indexing |
Index illustrations if icons table is empty (or --reindex) |
| 11. Frontend build |
npm ci (cached on package.json hash) + npm run build |
| 12. Frontend deploy |
rsync to /var/www/html/barclays-banner-builder/ |
| 13. Restart services |
docker compose up -d --no-deps --force-recreate api worker |
| 14. Apache config |
Insert Include fragment into vhost if not already present; apache2ctl configtest + systemctl reload apache2 |
| 15. Health check |
Curl /api/health — up to 15 retries with 2s sleep |
Port Allocation on Host
| Port |
Binding |
Service |
| 8010 |
127.0.0.1 |
FastAPI API (proxied by Apache) |
| 8000 |
(occupied by another project) |
Not used by this project |
| 8090 |
(not used in prod) |
Dev-only Nginx placeholder |
| 5174 |
0.0.0.0 (dev only) |
Vite dev server |