ADR-016: Local Reverse Proxy and Docker Compose Profiles
Status
Accepted
Context
PSSaaS will eventually run 5–8 Docker containers locally (documentation, API, frontend, cache, message bus, identity provider, mail capture). Without a routing strategy, each container would expose its own host port, leading to port sprawl — a problem already visible with the PowerSeller X project, which maps 14 containers across 16 host ports. Running both projects simultaneously would exceed 20 port mappings.
Additionally, not all containers are needed at every stage of development. During documentation-only work, standing up .NET, React, Redis, and Keycloak containers wastes resources and increases startup time.
Decision
-
Add an Nginx reverse proxy (
pssaas-proxy) as the single entry point for all PSSaaS services on port 80 viahttp://pssaas.powerseller.local/. All services are accessed via path-based routing:Path Service /docs/Docusaurus documentation /api/.NET 8 API /React frontend /auth/Identity provider /mail/Mailpit email capture -
Use Docker Compose profiles to organize services by need:
- Default (no profile):
proxy+docs— always available devprofile:api+web+cache— when application code existsfullprofile:identity+bus+mail— supporting infrastructure
- Default (no profile):
-
Remove host port mappings from all services except the proxy. Internal services communicate via Docker's default network.
-
Use runtime DNS resolution (Docker's internal resolver at
127.0.0.11with variable-basedproxy_pass) so Nginx starts and runs regardless of which profile services are active. Unavailable routes return HTTP 502 gracefully.
Consequences
Positive
- One hostname to remember. All of PSSaaS is at
http://pssaas.powerseller.local/, regardless of how many services are running. A hosts file entry mapspssaas.powerseller.localto127.0.0.1and the proxy listens on port 80 (default HTTP). - No port conflicts with the PSX project (which uses ports 3000, 3001, 3100, 3200, 5432, 6379, 8000, 8001, 8088, 8180, 9000–9001, 9090).
- Progressive startup.
docker compose upstarts fast (proxy + docs only). Heavier services activate only when needed. - Closer to production. Path-based routing through a reverse proxy mirrors how the application will be deployed in Azure (Azure Container Apps ingress or Azure Front Door).
- WebSocket support built in. HMR (Docusaurus, React) and future SignalR connections route through the proxy without issue.
Negative
- One more container. The Nginx proxy adds a lightweight (~5 MB) container.
- Path awareness required. Docusaurus needs
baseUrl: '/docs/'. Future React and .NET services need to be aware of their path prefix. - Debugging indirection. If a request fails, the developer must determine whether it's the proxy or the upstream service. Nginx access and error logs mitigate this.
Neutral
- Port 80 requires a hosts file entry (
127.0.0.1 pssaas.powerseller.local) on each developer workstation. This is a one-time setup step documented in the README.