Skip to main content

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

  1. Add an Nginx reverse proxy (pssaas-proxy) as the single entry point for all PSSaaS services on port 80 via http://pssaas.powerseller.local/. All services are accessed via path-based routing:

    PathService
    /docs/Docusaurus documentation
    /api/.NET 8 API
    /React frontend
    /auth/Identity provider
    /mail/Mailpit email capture
  2. Use Docker Compose profiles to organize services by need:

    • Default (no profile): proxy + docs — always available
    • dev profile: api + web + cache — when application code exists
    • full profile: identity + bus + mail — supporting infrastructure
  3. Remove host port mappings from all services except the proxy. Internal services communicate via Docker's default network.

  4. Use runtime DNS resolution (Docker's internal resolver at 127.0.0.11 with variable-based proxy_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 maps pssaas.powerseller.local to 127.0.0.1 and 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 up starts 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.