remove nginx, serve ui from api itself

This commit is contained in:
pratik
2025-10-15 14:22:44 -05:00
parent c5b85126c0
commit b8cabbe0c8
7 changed files with 91 additions and 45 deletions

View File

@@ -35,7 +35,9 @@
"Bash(git commit:*)", "Bash(git commit:*)",
"Bash(git merge:*)", "Bash(git merge:*)",
"Bash(git rm:*)", "Bash(git rm:*)",
"Bash(git checkout:*)" "Bash(git checkout:*)",
"Bash(git push:*)",
"Bash(Start-Sleep -Seconds 10)"
], ],
"deny": [], "deny": [],
"ask": [] "ask": []

View File

@@ -1,15 +1,39 @@
# Multi-stage build: First stage builds Angular frontend
FROM node:18-alpine as frontend-builder
# Install dependencies for native modules
RUN apk add --no-cache python3 make g++
WORKDIR /frontend
# Copy package files first for better layer caching
COPY frontend/package*.json ./
# Clean install dependencies
RUN npm ci --force
# Copy frontend source
COPY frontend/src ./src
COPY frontend/public ./public
COPY frontend/angular.json ./
COPY frontend/tsconfig*.json ./
# Build the Angular app for production
RUN npm run build
# Second stage: Python backend with Angular static files
FROM python:3.11-alpine FROM python:3.11-alpine
WORKDIR /app WORKDIR /app
# Install system dependencies for Alpine # Install system dependencies for Alpine
# Alpine uses apk instead of apt-get and is lighter/faster
RUN apk add --no-cache \ RUN apk add --no-cache \
gcc \ gcc \
musl-dev \ musl-dev \
postgresql-dev \ postgresql-dev \
postgresql-client \ postgresql-client \
linux-headers linux-headers \
curl
# Copy requirements and install Python dependencies # Copy requirements and install Python dependencies
COPY requirements.txt . COPY requirements.txt .
@@ -21,6 +45,9 @@ COPY utils/ ./utils/
COPY alembic/ ./alembic/ COPY alembic/ ./alembic/
COPY alembic.ini . COPY alembic.ini .
# Copy Angular build from frontend-builder stage
COPY --from=frontend-builder /frontend/dist/frontend/browser ./static
# Create non-root user (Alpine uses adduser instead of useradd) # Create non-root user (Alpine uses adduser instead of useradd)
RUN adduser -D -u 1000 appuser && chown -R appuser:appuser /app RUN adduser -D -u 1000 appuser && chown -R appuser:appuser /app
USER appuser USER appuser
@@ -30,7 +57,7 @@ EXPOSE 8000
# Health check # Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python -c "import requests; requests.get('http://localhost:8000/health')" CMD curl -f http://localhost:8000/health
# Run the application # Run the application
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -25,8 +25,8 @@ RUN npm run build --verbose
# Production image with nginx # Production image with nginx
FROM nginx:alpine FROM nginx:alpine
# Copy built Angular app # Copy built Angular app from the browser subdirectory
COPY --from=frontend-builder /frontend/dist/frontend /usr/share/nginx/html COPY --from=frontend-builder /frontend/dist/frontend/browser /usr/share/nginx/html
# Copy nginx configuration # Copy nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf

View File

@@ -1,5 +1,7 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from app.api.artifacts import router as artifacts_router from app.api.artifacts import router as artifacts_router
from app.api.seed import router as seed_router from app.api.seed import router as seed_router
from app.api.tags import router as tags_router from app.api.tags import router as tags_router
@@ -7,6 +9,7 @@ from app.database import init_db
from app.config import settings from app.config import settings
import logging import logging
import os import os
from pathlib import Path
# Configure logging # Configure logging
logging.basicConfig( logging.basicConfig(
@@ -39,7 +42,8 @@ app.include_router(artifacts_router)
app.include_router(seed_router) app.include_router(seed_router)
app.include_router(tags_router) app.include_router(tags_router)
# Note: Frontend is now served separately as an Angular application # Static files configuration - will be set up after routes
static_dir = Path("/app/static")
@app.on_event("startup") @app.on_event("startup")
@@ -65,16 +69,20 @@ async def api_root():
@app.get("/") @app.get("/")
async def ui_root(): async def serve_angular_app():
"""API root - Frontend is served separately""" """Serve Angular app index.html"""
return { static_dir = Path("/app/static")
"message": "Test Artifact Data Lake API", if static_dir.exists():
"version": "1.0.0", return FileResponse(static_dir / "index.html")
"docs": "/docs", else:
"frontend": "Frontend is served separately on port 4200 (development) or via reverse proxy (production)", # Fallback if static files not found
"deployment_mode": settings.deployment_mode, return {
"storage_backend": settings.storage_backend "message": "Test Artifact Data Lake API",
} "version": "1.0.0",
"docs": "/docs",
"deployment_mode": settings.deployment_mode,
"storage_backend": settings.storage_backend
}
@app.get("/health") @app.get("/health")
@@ -83,6 +91,31 @@ async def health_check():
return {"status": "healthy"} return {"status": "healthy"}
# Catch-all route for Angular client-side routing
# This must be last to not interfere with API routes
@app.get("/{full_path:path}")
async def catch_all(full_path: str):
"""Serve Angular app for all non-API routes (SPA routing)"""
if static_dir.exists():
# Check if the requested path is a file in the static directory
file_path = static_dir / full_path
if file_path.is_file() and file_path.exists():
# Determine media type based on file extension
media_type = None
if file_path.suffix == ".js":
media_type = "application/javascript"
elif file_path.suffix == ".css":
media_type = "text/css"
elif file_path.suffix in [".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico"]:
media_type = f"image/{file_path.suffix[1:]}"
return FileResponse(file_path, media_type=media_type)
# Otherwise, serve index.html for client-side routing
index_path = static_dir / "index.html"
if index_path.exists():
return FileResponse(index_path, media_type="text/html")
return {"error": "Static files not found"}
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run( uvicorn.run(

View File

@@ -34,7 +34,7 @@ services:
timeout: 5s timeout: 5s
retries: 5 retries: 5
api: app:
build: . build: .
ports: ports:
- "8000:8000" - "8000:8000"
@@ -52,25 +52,11 @@ services:
minio: minio:
condition: service_healthy condition: service_healthy
healthcheck: healthcheck:
test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:8000/health')"] test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s interval: 10s
timeout: 10s timeout: 5s
retries: 3 retries: 5
start_period: 40s
frontend:
build:
context: .
dockerfile: Dockerfile.frontend
ports:
- "4200:80"
depends_on:
api:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
volumes: volumes:
postgres_data: postgres_data:

View File

@@ -71,13 +71,13 @@ if ($Rebuild) {
if ($ComposeCmd -eq "docker compose") { if ($ComposeCmd -eq "docker compose") {
& docker compose down & docker compose down
Write-Host "Removing existing images for rebuild..." -ForegroundColor White Write-Host "Removing existing images for rebuild..." -ForegroundColor White
& docker compose down --rmi local 2>$null & docker compose down --rmi local
Write-Host "Building and starting all services..." -ForegroundColor White Write-Host "Building and starting all services..." -ForegroundColor White
& docker compose up -d --build & docker compose up -d --build
} else { } else {
& docker-compose down & docker-compose down
Write-Host "Removing existing images for rebuild..." -ForegroundColor White Write-Host "Removing existing images for rebuild..." -ForegroundColor White
& docker-compose down --rmi local 2>$null & docker-compose down --rmi local
Write-Host "Building and starting all services..." -ForegroundColor White Write-Host "Building and starting all services..." -ForegroundColor White
& docker-compose up -d --build & docker-compose up -d --build
} }
@@ -99,8 +99,7 @@ Write-Host "=========================================" -ForegroundColor Cyan
Write-Host "Complete Stack is running!" -ForegroundColor Green Write-Host "Complete Stack is running!" -ForegroundColor Green
Write-Host "=========================================" -ForegroundColor Cyan Write-Host "=========================================" -ForegroundColor Cyan
Write-Host "" Write-Host ""
Write-Host "Frontend: http://localhost:4200" -ForegroundColor White Write-Host "Application: http://localhost:8000" -ForegroundColor White
Write-Host "API: http://localhost:8000" -ForegroundColor White
Write-Host "API Docs: http://localhost:8000/docs" -ForegroundColor White Write-Host "API Docs: http://localhost:8000/docs" -ForegroundColor White
Write-Host "MinIO Console: http://localhost:9001" -ForegroundColor White Write-Host "MinIO Console: http://localhost:9001" -ForegroundColor White
Write-Host " Username: minioadmin" -ForegroundColor Gray Write-Host " Username: minioadmin" -ForegroundColor Gray
@@ -145,5 +144,5 @@ catch {
Write-Host "" Write-Host ""
Write-Host "=========================================" -ForegroundColor Cyan Write-Host "=========================================" -ForegroundColor Cyan
Write-Host "Setup complete!" -ForegroundColor Green Write-Host "Setup complete!" -ForegroundColor Green
Write-Host "Open http://localhost:4200 in your browser" -ForegroundColor Yellow Write-Host "Open http://localhost:8000 in your browser" -ForegroundColor Yellow
Write-Host "=========================================" -ForegroundColor Cyan Write-Host "=========================================" -ForegroundColor Cyan

View File

@@ -86,8 +86,7 @@ echo "========================================="
echo "Complete Stack is running! 🚀" echo "Complete Stack is running! 🚀"
echo "=========================================" echo "========================================="
echo "" echo ""
echo "Frontend: http://localhost:4200" echo "Application: http://localhost:8000"
echo "API: http://localhost:8000"
echo "API Docs: http://localhost:8000/docs" echo "API Docs: http://localhost:8000/docs"
echo "MinIO Console: http://localhost:9001" echo "MinIO Console: http://localhost:9001"
echo " Username: minioadmin" echo " Username: minioadmin"
@@ -125,5 +124,5 @@ fi
echo "=========================================" echo "========================================="
echo "Setup complete! 🚀" echo "Setup complete! 🚀"
echo "Open http://localhost:4200 in your browser" echo "Open http://localhost:8000 in your browser"
echo "=========================================" echo "========================================="