diff --git a/README.md b/README.md index 7059a96..728a368 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,43 @@ -# React + Vite +## Amigos App (React + Vite + Express) -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +Frontend (React/Vite) and backend (Express) are bundled into a single container for production. The backend serves the built frontend and exposes the API under `/api`. -Currently, two official plugins are available: +### Configuración del API en el frontend -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +- Variable: `VITE_API_BASE` +- Descripción: URL base del API para `fetch`. Si no se define, el frontend usa el mismo origen (recomendado detrás de Nginx). +- Ejemplos: + - Mismo origen (proxy Nginx al contenedor): no definir `VITE_API_BASE`. + - API en dominio diferente: `VITE_API_BASE=https://api.ejemplo.com` (requiere CORS). -## Expanding the ESLint configuration +### Despliegue con Nginx (recomendado: mismo origen) -If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. +Proxy del dominio al contenedor (sirve estáticos y `/api`): + +``` +server { + server_name amigos.nucleoriofrio.com; + + # Opcional: gzip, TLS, etc. + + location / { + proxy_pass http://amigos-app:3001; # nombre del servicio Docker + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +Con esta configuración, no definas `VITE_API_BASE` para que el frontend use rutas relativas (`/api/...`). + +### Docker Compose + +El servicio expone el puerto 3001 dentro de la red de Docker. Asegúrate de que Nginx esté en la misma red (por ejemplo, `principal`) para alcanzar `amigos-app:3001`. + +### Diagnóstico rápido + +- 200 en `https://amigos.nucleoriofrio.com/health` indica que el backend está arriba. +- Si el navegador muestra `ERR_CONNECTION_REFUSED`, revisa que el frontend no apunte a `http://localhost:3001` (usa `VITE_API_BASE` o mismo origen). diff --git a/docker-compose.yml b/docker-compose.yml index 366a017..54537ba 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,13 +4,15 @@ services: amigos-app: image: gitea.nucleoriofrio.com/nucleo000/amigos-app:latest container_name: amigos-app - expose: + ports: - "3001" environment: - MONGO_HOST=mongodb-local - PORT=3001 + - NODE_ENV=production depends_on: - mongodb + restart: unless-stopped networks: - principal - amigos-network @@ -24,6 +26,8 @@ services: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=MongoPass2024! - MONGO_INITDB_DATABASE=testdb + + restart: unless-stopped networks: - amigos-network @@ -31,4 +35,4 @@ networks: principal: external: true amigos-network: - driver: bridge \ No newline at end of file + driver: bridge diff --git a/src/App.jsx b/src/App.jsx index baf4f7f..9e3f083 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,9 @@ import { useState, useEffect } from 'react' import './App.css' +// Configure API base URL via Vite env, default to same-origin +const API_BASE = import.meta.env.VITE_API_BASE || '' + function App() { const [nombre, setNombre] = useState('') const [amigos, setAmigos] = useState([]) @@ -13,7 +16,7 @@ function App() { const fetchAmigos = async () => { try { - const response = await fetch('http://localhost:3001/api/amigos') + const response = await fetch(`${API_BASE}/api/amigos`) const data = await response.json() setAmigos(data) } catch (error) { @@ -33,7 +36,7 @@ function App() { setMessage('') try { - const response = await fetch('http://localhost:3001/api/amigos', { + const response = await fetch(`${API_BASE}/api/amigos`, { method: 'POST', headers: { 'Content-Type': 'application/json',