Nginx sits at the front of the Tradiciones y Sabores stack, handling two distinct responsibilities: serving the compiled React single-page application as static files, and transparently forwarding every request that begins withDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/teofilobetancourt/Tradiciones-y-Sabores/llms.txt
Use this file to discover all available pages before exploring further.
/api/ to the FastAPI backend running on port 5000. This dual-role setup means the browser only ever talks to one origin (port 80), eliminating cross-origin issues entirely and avoiding the need for any CORS preflight on API calls made from the frontend bundle.
Docker Configuration — nginx.docker.conf
This file is copied into the Nginx container image at build time and becomes the active server block for the production Docker deployment:Key Directives Explained
Static file root
root directive points to the directory where the Vite production build is copied during the Docker image build. Every static asset—JavaScript bundles, CSS, images, and the index.html entry point—is served directly from this path by Nginx without any application-layer involvement.
SPA fallback with try_files
http://localhost/orders would cause Nginx to look for a real file at that path, find nothing, and return a 404. The try_files chain instructs Nginx to first look for a matching file ($uri), then a matching directory ($uri/), and finally fall back to serving index.html so React Router can take over and render the correct view.
API reverse proxy
/api/v1/ are forwarded to http://backend:5000/api/, where backend resolves to the tradiciones_sabores_api container via Docker’s internal DNS. The path rewrite strips the /v1 prefix so the FastAPI router receives the paths it expects (e.g., /api/ordenes). The broader /api/ block catches utility paths like /api/docs and /api/debug and forwards them verbatim to the backend.
Swagger UI and OpenAPI schema
nginx.conf vs nginx.docker.conf
Two Nginx configuration files exist in the repository, each targeting a different runtime environment:| Feature | nginx.docker.conf (Docker) | nginx.conf (Local / Bare-Metal) |
|---|---|---|
Backend hostname in proxy_pass | backend:5000 (Docker DNS) | 127.0.0.1:5000 (localhost loopback) |
| Proxy timeout headers | Not set | proxy_read_timeout 60s, proxy_connect_timeout 10s |
| Asset caching | Not configured | expires 1y + Cache-Control: public, immutable on /assets/ |
| Gzip compression | Not configured | Enabled for HTML, CSS, JS, JSON, SVG |
| Security headers | Not set | X-Frame-Options, X-Content-Type-Options, X-XSS-Protection |
/api/docs alias | Not present | Proxies /api/docs → http://127.0.0.1:5000/docs |
proxy_pass uses the service name backend. On a bare-metal server where both Nginx and Uvicorn run as host processes, proxy_pass targets 127.0.0.1.
Multi-Stage Frontend Dockerfile
The rootDockerfile builds the React application and packages it into a minimal Nginx image using two separate stages:
node:20-alpine AS build
All Node.js tooling, node_modules, TypeScript source files, and Vite internals are present only in this intermediate layer. Running npm ci ensures a clean, reproducible install from package-lock.json. The VITE_API_URL and VITE_API_KEY build arguments let CI/CD pipelines inject environment-specific values at build time. npm run build produces an optimised static bundle in /app/dist.
Stage 2 — nginx:alpine
Only two things are copied into the final image: the compiled /app/dist output (now placed at /var/www/tradicionesysabores) and the nginx.docker.conf server block. Every Node.js binary, source file, and build dependency is discarded, resulting in a final image that is just Nginx plus static HTML/CSS/JS.
The multi-stage build produces a significantly smaller Docker image than a single-stage approach. The
nginx:alpine base image is roughly 10 MB, and the compiled React bundle typically adds fewer than 5 MB—keeping the final frontend image under 20 MB and reducing the attack surface in production.