feat(deploy): Añade configuración Docker para despliegue de servicios
This commit is contained in:
		
							
								
								
									
										63
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | services: | ||||||
|  |   # Servicio del Backend API | ||||||
|  |   mercados-api: | ||||||
|  |     build: | ||||||
|  |       context: ./MercadosModernos # Asumiendo que clonaste el repo en esta carpeta | ||||||
|  |       dockerfile: src/Mercados.Api/Dockerfile | ||||||
|  |     container_name: mercados-api | ||||||
|  |     restart: always | ||||||
|  |     env_file: | ||||||
|  |       - ./.env # Lee las variables desde un archivo .env en la misma carpeta | ||||||
|  |     networks: | ||||||
|  |       - mercados-net | ||||||
|  |       - shared-net # Se conecta a la red compartida para hablar con la DB | ||||||
|  |     # NO se exponen puertos al host. | ||||||
|  |  | ||||||
|  |   # Servicio del Worker | ||||||
|  |   mercados-worker: | ||||||
|  |     build: | ||||||
|  |       context: ./MercadosModernos | ||||||
|  |       dockerfile: src/Mercados.Worker/Dockerfile | ||||||
|  |     container_name: mercados-worker | ||||||
|  |     restart: always | ||||||
|  |     env_file: | ||||||
|  |       - ./.env | ||||||
|  |     networks: | ||||||
|  |       - shared-net # Solo necesita acceso a la DB. | ||||||
|  |     # NO se exponen puertos al host. | ||||||
|  |  | ||||||
|  |   # Servicio del Frontend (servido por Nginx) | ||||||
|  |   mercados-frontend: | ||||||
|  |     build: | ||||||
|  |       context: ./MercadosModernos/frontend | ||||||
|  |       dockerfile: Dockerfile | ||||||
|  |     container_name: mercados-frontend | ||||||
|  |     restart: always | ||||||
|  |     networks: | ||||||
|  |       - mercados-net | ||||||
|  |     # NO se exponen puertos al host. | ||||||
|  |  | ||||||
|  |   # --- NUEVO SERVICIO: Proxy Inverso Local --- | ||||||
|  |   proxy: | ||||||
|  |     image: nginx:1.25-alpine | ||||||
|  |     container_name: mercados-proxy | ||||||
|  |     restart: always | ||||||
|  |     volumes: | ||||||
|  |       # Mapeamos nuestro archivo de configuración al contenedor de Nginx | ||||||
|  |       - ./proxy-local/nginx.conf:/etc/nginx/conf.d/default.conf | ||||||
|  |     ports: | ||||||
|  |       # ESTE ES EL ÚNICO PUNTO DE ENTRADA DESDE EL EXTERIOR | ||||||
|  |       # Expone el puerto 80 del contenedor al puerto 8500 del host Debian. | ||||||
|  |       - "8500:80" | ||||||
|  |     networks: | ||||||
|  |       - mercados-net | ||||||
|  |     depends_on: | ||||||
|  |       - mercados-api | ||||||
|  |       - mercados-frontend | ||||||
|  |  | ||||||
|  | networks: | ||||||
|  |   mercados-net: | ||||||
|  |     driver: bridge | ||||||
|  |  | ||||||
|  |   shared-net: | ||||||
|  |     external: true | ||||||
							
								
								
									
										28
									
								
								frontend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								frontend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | # --- Etapa 1: Build --- | ||||||
|  | # Usamos una imagen ligera de Node.js para instalar dependencias y compilar el frontend | ||||||
|  | FROM node:20-alpine AS build | ||||||
|  | WORKDIR /app | ||||||
|  |  | ||||||
|  | # Copiamos package.json y package-lock.json para cachear las dependencias | ||||||
|  | COPY package*.json ./ | ||||||
|  | RUN npm install | ||||||
|  |  | ||||||
|  | # Copiamos el resto del código del frontend | ||||||
|  | COPY . . | ||||||
|  | # Ejecutamos el script de build de Vite | ||||||
|  | RUN npm run build | ||||||
|  |  | ||||||
|  | # --- Etapa 2: Producción --- | ||||||
|  | # Usamos la imagen oficial de Nginx, que es muy pequeña y eficiente | ||||||
|  | FROM nginx:1.25-alpine | ||||||
|  |  | ||||||
|  | # Copiamos los archivos estáticos generados en la etapa de build | ||||||
|  | # a la carpeta que Nginx sirve por defecto. | ||||||
|  | COPY --from=build /app/dist /usr/share/nginx/html | ||||||
|  |  | ||||||
|  | # Nginx ya está configurado para escuchar en el puerto 80 por defecto. | ||||||
|  | # Simplemente lo exponemos. | ||||||
|  | EXPOSE 80 | ||||||
|  |  | ||||||
|  | # El comando por defecto de la imagen de Nginx ya inicia el servidor. | ||||||
|  | CMD ["nginx", "-g", "daemon off;"] | ||||||
							
								
								
									
										25
									
								
								frontend/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								frontend/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | server { | ||||||
|  |     listen 80; | ||||||
|  |     server_name widgets.eldia.com; | ||||||
|  |  | ||||||
|  |     # Ubicación raíz para servir los archivos estáticos del frontend | ||||||
|  |     root /usr/share/nginx/html; | ||||||
|  |     index index.html; | ||||||
|  |  | ||||||
|  |     # Configuración para las rutas del frontend | ||||||
|  |     location / { | ||||||
|  |         try_files $uri $uri/ /index.html; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     # --- Proxy Inverso para la API --- | ||||||
|  |     # Todas las peticiones que empiecen con /api/ se redirigen al backend | ||||||
|  |     location /api/ { | ||||||
|  |         # El nombre 'backend-api' debe coincidir con el nombre del servicio en docker-compose.yml | ||||||
|  |         # El puerto 8080 es el puerto que expone el contenedor de la API (no el host) | ||||||
|  |         proxy_pass http://backend-api:8080;  | ||||||
|  |         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; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -62,8 +62,8 @@ export const RawBolsaUsaTable = () => { | |||||||
|                             <TableRow key={row.id}> |                             <TableRow key={row.id}> | ||||||
|                                 <TableCell>{row.ticker}</TableCell> |                                 <TableCell>{row.ticker}</TableCell> | ||||||
|                                 <TableCell>{row.nombreEmpresa}</TableCell> |                                 <TableCell>{row.nombreEmpresa}</TableCell> | ||||||
|                                 <TableCell align="right">${formatCurrency(row.precioActual, 'USD')}</TableCell> |                                 <TableCell align="right">{formatCurrency(row.precioActual, 'USD')}</TableCell> | ||||||
|                                 <TableCell align="right">${formatCurrency(row.cierreAnterior, 'USD')}</TableCell> |                                 <TableCell align="right">{formatCurrency(row.cierreAnterior, 'USD')}</TableCell> | ||||||
|                                 <TableCell align="right">{row.porcentajeCambio.toFixed(2)}%</TableCell> |                                 <TableCell align="right">{row.porcentajeCambio.toFixed(2)}%</TableCell> | ||||||
|                                 <TableCell>{formatFullDateTime(row.fechaRegistro)}</TableCell> |                                 <TableCell>{formatFullDateTime(row.fechaRegistro)}</TableCell> | ||||||
|                             </TableRow> |                             </TableRow> | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								src/Mercados.Api/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/Mercados.Api/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | # --- Etapa 1: Build --- | ||||||
|  | # Usamos la imagen del SDK de .NET 8 para compilar la aplicación | ||||||
|  | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build | ||||||
|  | WORKDIR /src | ||||||
|  |  | ||||||
|  | # Copiamos los archivos .csproj de cada proyecto para restaurar las dependencias de forma eficiente | ||||||
|  | COPY ["src/Mercados.Api/Mercados.Api.csproj", "Mercados.Api/"] | ||||||
|  | COPY ["src/Mercados.Infrastructure/Mercados.Infrastructure.csproj", "Mercados.Infrastructure/"] | ||||||
|  | COPY ["src/Mercados.Core/Mercados.Core.csproj", "Mercados.Core/"] | ||||||
|  | COPY ["src/Mercados.Database/Mercados.Database.csproj", "Mercados.Database/"] | ||||||
|  | RUN dotnet restore "Mercados.Api/Mercados.Api.csproj" | ||||||
|  |  | ||||||
|  | # Copiamos el resto del código fuente | ||||||
|  | COPY src/. . | ||||||
|  |  | ||||||
|  | # Publicamos la aplicación en modo Release, optimizada para producción | ||||||
|  | WORKDIR "/src/Mercados.Api" | ||||||
|  | RUN dotnet publish "Mercados.Api.csproj" -c Release -o /app/publish | ||||||
|  |  | ||||||
|  | # --- Etapa 2: Final --- | ||||||
|  | # Usamos la imagen de runtime de ASP.NET, que es mucho más ligera que la del SDK | ||||||
|  | FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final | ||||||
|  | WORKDIR /app | ||||||
|  | COPY --from=build /app/publish . | ||||||
|  |  | ||||||
|  | # Definimos el punto de entrada para ejecutar la aplicación cuando el contenedor arranque | ||||||
|  | ENTRYPOINT ["dotnet", "Mercados.Api.dll"] | ||||||
| @@ -16,7 +16,7 @@ namespace Mercados.Infrastructure.DataFetchers | |||||||
|             // Empresas 'Latinas' en Wall Street |             // Empresas 'Latinas' en Wall Street | ||||||
|             "MELI", "GLOB", |             "MELI", "GLOB", | ||||||
|             // ADRs Argentinos |             // ADRs Argentinos | ||||||
|             "YPF", "GGAL", "BMA", "LOMA", "PAM", "TEO", "TGS", "EDN", "CRESY", "CEPU", "BBAR" |             "YPF", "GGAL", "BMA", "LOMA", "TEO", "TGS", "EDN", "BBAR" | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         private readonly FinnhubClient _client; |         private readonly FinnhubClient _client; | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								src/Mercados.Worker/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Mercados.Worker/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # --- Etapa 1: Build --- | ||||||
|  | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build | ||||||
|  | WORKDIR /src | ||||||
|  |  | ||||||
|  | # Copiamos los archivos .csproj y restauramos | ||||||
|  | COPY ["src/Mercados.Worker/Mercados.Worker.csproj", "Mercados.Worker/"] | ||||||
|  | COPY ["src/Mercados.Infrastructure/Mercados.Infrastructure.csproj", "Mercados.Infrastructure/"] | ||||||
|  | COPY ["src/Mercados.Core/Mercados.Core.csproj", "Mercados.Core/"] | ||||||
|  | RUN dotnet restore "Mercados.Worker/Mercados.Worker.csproj" | ||||||
|  |  | ||||||
|  | # Copiamos el resto del código | ||||||
|  | COPY src/. . | ||||||
|  |  | ||||||
|  | # Publicamos la aplicación | ||||||
|  | WORKDIR "/src/Mercados.Worker" | ||||||
|  | RUN dotnet publish "Mercados.Worker.csproj" -c Release -o /app/publish | ||||||
|  |  | ||||||
|  | # --- Etapa 2: Final --- | ||||||
|  | # Usamos la imagen de runtime genérica de .NET, no la de ASP.NET | ||||||
|  | FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final | ||||||
|  | WORKDIR /app | ||||||
|  | COPY --from=build /app/publish . | ||||||
|  | ENTRYPOINT ["dotnet", "Mercados.Worker.dll"] | ||||||
		Reference in New Issue
	
	Block a user