refactor nginx
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
This commit is contained in:
205
web/DEVELOPMENT.md
Normal file
205
web/DEVELOPMENT.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# Guía de Desarrollo
|
||||
|
||||
## Configuración de Puertos
|
||||
|
||||
### Desarrollo Local
|
||||
| Servicio | Puerto | URL |
|
||||
|----------|--------|-----|
|
||||
| Dashboard (Vue) | 3000 | http://localhost:3000 |
|
||||
| Backend (API) | 3001 | http://localhost:3001 |
|
||||
| Landing (Astro) | 3002 | http://localhost:3002 |
|
||||
|
||||
### Producción (Docker)
|
||||
| Servicio | Puerto Externo | Puerto Interno |
|
||||
|----------|----------------|----------------|
|
||||
| Nginx Proxy | 80 | - |
|
||||
| Dashboard | - | 80 |
|
||||
| Backend | - | 3001 |
|
||||
| Landing | - | 80 |
|
||||
|
||||
## Ejecutar en Desarrollo Local
|
||||
|
||||
### 1. Backend (API)
|
||||
|
||||
```bash
|
||||
cd web/backend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
El backend estará disponible en `http://localhost:3001`
|
||||
|
||||
**Endpoints**:
|
||||
- API: `http://localhost:3001/api/*`
|
||||
- WebSocket: `ws://localhost:3001/ws`
|
||||
|
||||
### 2. Dashboard (Vue)
|
||||
|
||||
```bash
|
||||
cd web/dashboard
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
El dashboard estará disponible en `http://localhost:3000`
|
||||
|
||||
**Nota**: Vite está configurado con proxy automático:
|
||||
- `/api/*` → `http://localhost:3001/api/*`
|
||||
- `/ws` → `ws://localhost:3001/ws`
|
||||
|
||||
Esto significa que puedes hacer peticiones a `/api/users` desde el dashboard y automáticamente se redirigirán al backend.
|
||||
|
||||
### 3. Landing (Astro)
|
||||
|
||||
```bash
|
||||
cd web/landing
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
La landing estará disponible en `http://localhost:3002`
|
||||
|
||||
## Ejecutar con Docker (Producción)
|
||||
|
||||
```bash
|
||||
# Construir imágenes
|
||||
docker-compose build
|
||||
|
||||
# Iniciar servicios
|
||||
docker-compose up -d
|
||||
|
||||
# Ver logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Detener servicios
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
Todo estará disponible en `http://localhost`:
|
||||
- Landing: `http://localhost/`
|
||||
- Dashboard: `http://localhost/dashboard/`
|
||||
- API: `http://localhost/api/`
|
||||
|
||||
## Reconstruir después de cambios
|
||||
|
||||
### Cambios en código (desarrollo)
|
||||
|
||||
No es necesario hacer nada, Vite y Node tienen hot-reload automático.
|
||||
|
||||
### Cambios en configuración o Docker
|
||||
|
||||
```bash
|
||||
# Reconstruir servicio específico
|
||||
docker-compose build dashboard
|
||||
docker-compose build backend
|
||||
docker-compose build landing
|
||||
|
||||
# Reconstruir todo
|
||||
docker-compose build
|
||||
|
||||
# Reiniciar servicios
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Diferencias entre Desarrollo y Producción
|
||||
|
||||
### Dashboard
|
||||
- **Desarrollo**:
|
||||
- Puerto 3000
|
||||
- Vite proxy activo para `/api` y `/ws`
|
||||
- Hot Module Replacement (HMR)
|
||||
- Source maps
|
||||
|
||||
- **Producción**:
|
||||
- Puerto 80 (interno)
|
||||
- Sin proxy (nginx principal maneja todo)
|
||||
- Código minificado y optimizado
|
||||
- Assets con hash para cache
|
||||
|
||||
### Backend
|
||||
- **Desarrollo**:
|
||||
- Puerto 3001
|
||||
- `node --watch` para auto-reload
|
||||
- Variables de entorno por defecto
|
||||
|
||||
- **Producción**:
|
||||
- Puerto 3001 (interno)
|
||||
- `node` sin watch
|
||||
- Variables de entorno de Docker
|
||||
|
||||
### Landing
|
||||
- **Desarrollo**:
|
||||
- Puerto 3002
|
||||
- Servidor de desarrollo de Astro
|
||||
- Hot reload
|
||||
|
||||
- **Producción**:
|
||||
- Puerto 80 (interno)
|
||||
- Archivos estáticos servidos por nginx
|
||||
- Pre-renderizado
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Puerto ya en uso
|
||||
|
||||
```bash
|
||||
# Ver qué está usando el puerto
|
||||
lsof -i :3000 # Dashboard
|
||||
lsof -i :3001 # Backend
|
||||
lsof -i :3002 # Landing
|
||||
|
||||
# Matar proceso
|
||||
kill -9 <PID>
|
||||
```
|
||||
|
||||
### Proxy no funciona en desarrollo
|
||||
|
||||
Asegúrate de que:
|
||||
1. El backend está corriendo en el puerto 3001
|
||||
2. Estás ejecutando `npm run dev` (modo desarrollo)
|
||||
3. La configuración de proxy en `vite.config.js` está correcta
|
||||
|
||||
### Assets 404 en producción
|
||||
|
||||
Ver `NGINX_CONFIG.md` para detalles de configuración de nginx y assets.
|
||||
|
||||
## Variables de Entorno
|
||||
|
||||
### Backend (desarrollo local)
|
||||
|
||||
Crear archivo `.env` en `web/backend/`:
|
||||
|
||||
```env
|
||||
PORT=3001
|
||||
PROJECT_ROOT=/ruta/al/proyecto
|
||||
MONGODB_HOST=localhost
|
||||
MONGODB_PORT=27017
|
||||
MONGODB_DATABASE=wallabicher
|
||||
MONGODB_USERNAME=admin
|
||||
MONGODB_PASSWORD=adminpassword
|
||||
```
|
||||
|
||||
### Backend (Docker)
|
||||
|
||||
Las variables se configuran en `docker-compose.yml`:
|
||||
- `PORT=3001`
|
||||
- `PROJECT_ROOT=/data`
|
||||
- Credenciales de MongoDB
|
||||
|
||||
## Base URLs
|
||||
|
||||
### Dashboard
|
||||
|
||||
La configuración de `base: '/dashboard/'` en `vite.config.js` hace que:
|
||||
- Todos los assets se construyan con prefijo `/dashboard/`
|
||||
- Vue Router use `/dashboard` como base
|
||||
- Service Worker se registre en `/dashboard/sw.js`
|
||||
|
||||
**No cambiar** a menos que quieras cambiar la ruta del dashboard.
|
||||
|
||||
### Landing
|
||||
|
||||
Sin base (raíz por defecto). Se sirve desde `/`.
|
||||
|
||||
**No cambiar** a menos que quieras mover la landing a otra ruta.
|
||||
|
||||
139
web/NGINX_CONFIG.md
Normal file
139
web/NGINX_CONFIG.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Configuración de Nginx y Assets
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
Usuario
|
||||
↓
|
||||
nginx (proxy principal) :80
|
||||
├─→ /api → backend:3001
|
||||
├─→ /ws → backend:3001
|
||||
├─→ /dashboard → dashboard:80
|
||||
└─→ / → landing:80
|
||||
```
|
||||
|
||||
## Configuración de rutas
|
||||
|
||||
### 1. Dashboard (Vue + Vite)
|
||||
|
||||
**Base URL**: `/dashboard/`
|
||||
|
||||
- **Vite config**: `base: '/dashboard/'` (siempre)
|
||||
- **Vue Router**: `createWebHistory('/dashboard')`
|
||||
- **Nginx interno**: Sirve desde `/usr/share/nginx/html/dashboard/`
|
||||
- **Assets**: Se construyen con prefijo `/dashboard/` automáticamente por Vite
|
||||
|
||||
**Flujo de peticiones**:
|
||||
```
|
||||
Usuario → http://localhost/dashboard/
|
||||
↓
|
||||
nginx proxy → http://dashboard:80/dashboard/
|
||||
↓
|
||||
nginx dashboard → /usr/share/nginx/html/dashboard/index.html
|
||||
```
|
||||
|
||||
**Assets**:
|
||||
```
|
||||
Usuario → http://localhost/dashboard/assets/index-abc123.js
|
||||
↓
|
||||
nginx proxy → http://dashboard:80/dashboard/assets/index-abc123.js
|
||||
↓
|
||||
nginx dashboard → /usr/share/nginx/html/dashboard/assets/index-abc123.js
|
||||
```
|
||||
|
||||
### 2. Landing (Astro)
|
||||
|
||||
**Base URL**: `/`
|
||||
|
||||
- **Astro config**: Sin base (raíz por defecto)
|
||||
- **Nginx interno**: Sirve desde `/usr/share/nginx/html/`
|
||||
- **Assets**: Se construyen para la raíz
|
||||
|
||||
**Flujo de peticiones**:
|
||||
```
|
||||
Usuario → http://localhost/
|
||||
↓
|
||||
nginx proxy → http://landing:80/
|
||||
↓
|
||||
nginx landing → /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
## Puertos
|
||||
|
||||
### Desarrollo local
|
||||
```
|
||||
Dashboard (Vue): http://localhost:3000
|
||||
Backend (API): http://localhost:3001
|
||||
Landing (Astro): http://localhost:3002
|
||||
```
|
||||
|
||||
### Producción (Docker)
|
||||
```
|
||||
nginx (proxy): :80 (externo)
|
||||
├─ dashboard: :80 (interno)
|
||||
├─ backend: :3001 (interno)
|
||||
└─ landing: :80 (interno)
|
||||
```
|
||||
|
||||
## Desarrollo local
|
||||
|
||||
Para desarrollo local, el proxy de Vite está configurado solo para `mode === 'development'`:
|
||||
|
||||
```bash
|
||||
# Terminal 1: Backend
|
||||
cd web/backend
|
||||
npm run dev
|
||||
# → API en http://localhost:3001
|
||||
|
||||
# Terminal 2: Dashboard
|
||||
cd web/dashboard
|
||||
npm run dev
|
||||
# → Dashboard en http://localhost:3000
|
||||
# → Vite proxy activo: /api → localhost:3001, /ws → localhost:3001
|
||||
|
||||
# Terminal 3: Landing
|
||||
cd web/landing
|
||||
npm run dev
|
||||
# → Landing en http://localhost:3002
|
||||
|
||||
# Producción (Docker)
|
||||
docker-compose up -d
|
||||
# → Todo en http://localhost:80
|
||||
```
|
||||
|
||||
## Reconstruir después de cambios
|
||||
|
||||
Si cambias la configuración de nginx o los archivos de configuración:
|
||||
|
||||
```bash
|
||||
# Reconstruir solo el dashboard
|
||||
docker-compose build dashboard
|
||||
|
||||
# Reconstruir solo la landing
|
||||
docker-compose build landing
|
||||
|
||||
# Reconstruir todo
|
||||
docker-compose build
|
||||
|
||||
# Reiniciar servicios
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Assets 404 en dashboard
|
||||
|
||||
1. Verificar que Vite construyó con `base: '/dashboard/'`
|
||||
2. Verificar que el Dockerfile copia a `/usr/share/nginx/html/dashboard`
|
||||
3. Verificar que nginx-dashboard.conf tiene la location `/dashboard/`
|
||||
|
||||
### Assets 404 en landing
|
||||
|
||||
1. Verificar que Astro construyó sin base (raíz)
|
||||
2. Verificar que el Dockerfile copia a `/usr/share/nginx/html/`
|
||||
3. Verificar que nginx landing usa root `/usr/share/nginx/html`
|
||||
|
||||
### Service Worker no se registra
|
||||
|
||||
El Service Worker debe estar en `/dashboard/sw.js` y registrarse con scope `/dashboard/`
|
||||
|
||||
@@ -11,14 +11,14 @@ RUN npm ci
|
||||
# Copiar código fuente
|
||||
COPY . .
|
||||
|
||||
# Construir aplicación
|
||||
# Construir aplicación con base /dashboard/
|
||||
RUN npm run build
|
||||
|
||||
# Stage de producción - servir con nginx
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copiar archivos construidos
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
# Copiar archivos construidos (ya incluyen el prefijo /dashboard en las rutas)
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html/dashboard
|
||||
|
||||
# Copiar configuración de nginx (se puede sobrescribir con volumen)
|
||||
COPY nginx-dashboard.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
@@ -10,15 +10,22 @@ server {
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
|
||||
|
||||
# SPA routing - todas las rutas del dashboard
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Dashboard assets con prefijo /dashboard/
|
||||
location /dashboard/ {
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# SPA routing - todas las rutas del dashboard
|
||||
try_files $uri $uri/ /dashboard/index.html;
|
||||
}
|
||||
|
||||
# Redirigir raíz al dashboard
|
||||
location = / {
|
||||
return 301 /dashboard/;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,42 +8,24 @@ server {
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json;
|
||||
|
||||
# SPA routing
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# API proxy
|
||||
location /api {
|
||||
proxy_pass http://backend:3001;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
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;
|
||||
}
|
||||
|
||||
# WebSocket proxy
|
||||
location /ws {
|
||||
proxy_pass http://backend:3001;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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;
|
||||
}
|
||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
|
||||
|
||||
# Dashboard assets con prefijo /dashboard/
|
||||
location /dashboard/ {
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# SPA routing - todas las rutas del dashboard
|
||||
try_files $uri $uri/ /dashboard/index.html;
|
||||
}
|
||||
|
||||
# Redirigir raíz al dashboard
|
||||
location = / {
|
||||
return 301 /dashboard/;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ self.addEventListener('push', (event) => {
|
||||
let notificationData = {
|
||||
title: 'Wallabicher',
|
||||
body: 'Tienes nuevas notificaciones',
|
||||
icon: '/android-chrome-192x192.png',
|
||||
badge: '/android-chrome-192x192.png',
|
||||
icon: '/dashboard/android-chrome-192x192.png',
|
||||
badge: '/dashboard/android-chrome-192x192.png',
|
||||
tag: 'wallabicher-notification',
|
||||
requireInteraction: false,
|
||||
data: {}
|
||||
@@ -89,7 +89,7 @@ self.addEventListener('notificationclick', (event) => {
|
||||
} else {
|
||||
// Si no hay URL, abrir la app
|
||||
event.waitUntil(
|
||||
clients.openWindow('/')
|
||||
clients.openWindow('/dashboard/')
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -105,8 +105,8 @@ app.mount('#app');
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', async () => {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.register('/sw.js', {
|
||||
scope: '/'
|
||||
const registration = await navigator.serviceWorker.register('/dashboard/sw.js', {
|
||||
scope: '/dashboard/'
|
||||
});
|
||||
console.log('Service Worker registrado:', registration.scope);
|
||||
} catch (error) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { fileURLToPath, URL } from 'url';
|
||||
|
||||
export default defineConfig({
|
||||
export default defineConfig(({ mode }) => ({
|
||||
plugins: [vue()],
|
||||
base: '/dashboard/',
|
||||
resolve: {
|
||||
@@ -12,7 +12,9 @@ export default defineConfig({
|
||||
},
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
host: true,
|
||||
// Proxy solo para desarrollo local
|
||||
proxy: mode === 'development' ? {
|
||||
'/api': {
|
||||
target: 'http://localhost:3001',
|
||||
changeOrigin: true,
|
||||
@@ -21,7 +23,7 @@ export default defineConfig({
|
||||
target: 'ws://localhost:3001',
|
||||
ws: true,
|
||||
},
|
||||
} : undefined,
|
||||
},
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
@@ -17,11 +17,8 @@ RUN npm run build
|
||||
# Stage de producción - servir con nginx
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copiar archivos construidos
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html/landing
|
||||
|
||||
#change /usr/share/nginx/html to /usr/share/nginx/html/landing
|
||||
RUN sed -i 's|/usr/share/nginx/html|/usr/share/nginx/html/landing|g' /etc/nginx/conf.d/default.conf
|
||||
# Copiar archivos construidos a la raíz
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
# Exponer puerto
|
||||
EXPOSE 80
|
||||
|
||||
@@ -5,5 +5,9 @@ import tailwind from '@astrojs/tailwind';
|
||||
export default defineConfig({
|
||||
integrations: [tailwind()],
|
||||
output: 'static',
|
||||
server: {
|
||||
port: 3002,
|
||||
host: true,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -33,17 +33,7 @@ server {
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Login también va al dashboard
|
||||
location /login {
|
||||
proxy_pass http://dashboard:80;
|
||||
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;
|
||||
}
|
||||
|
||||
# Dashboard Vue
|
||||
# Dashboard Vue - pasar petición completa con prefijo /dashboard
|
||||
location /dashboard {
|
||||
proxy_pass http://dashboard:80;
|
||||
proxy_http_version 1.1;
|
||||
@@ -51,10 +41,6 @@ server {
|
||||
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;
|
||||
|
||||
# Para SPA routing dentro de /dashboard - quitar el prefijo /dashboard
|
||||
rewrite ^/dashboard/(.*)$ /$1 break;
|
||||
rewrite ^/dashboard$ / break;
|
||||
}
|
||||
|
||||
# Landing page (Astro) - raíz
|
||||
@@ -66,11 +52,5 @@ server {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user