f/app #2
4
.gitignore
vendored
4
.gitignore
vendored
@@ -86,3 +86,7 @@ helm/charts/
|
||||
tmp/
|
||||
temp/
|
||||
*.tmp
|
||||
|
||||
# Node.js
|
||||
package-lock.json
|
||||
**/package-lock.json
|
||||
|
||||
31
Dockerfile
31
Dockerfile
@@ -1,3 +1,30 @@
|
||||
# Multi-stage build: First stage builds Angular frontend
|
||||
FROM node:24-alpine AS frontend-build
|
||||
|
||||
# Accept npm registry as build argument
|
||||
ARG NPM_REGISTRY=https://registry.npmjs.org/
|
||||
|
||||
WORKDIR /frontend
|
||||
|
||||
# Copy package files
|
||||
COPY frontend/package*.json ./
|
||||
|
||||
# Configure npm registry if custom registry is provided
|
||||
RUN if [ "$NPM_REGISTRY" != "https://registry.npmjs.org/" ]; then \
|
||||
echo "Using custom npm registry: $NPM_REGISTRY"; \
|
||||
npm config set registry "$NPM_REGISTRY"; \
|
||||
fi
|
||||
|
||||
# Install dependencies (ignore package-lock.json if using custom registry)
|
||||
RUN npm install
|
||||
|
||||
# Copy source code
|
||||
COPY frontend/ ./
|
||||
|
||||
# Build for production
|
||||
RUN npm run build:prod
|
||||
|
||||
# Second stage: Python backend with Angular frontend
|
||||
FROM python:3.11-alpine
|
||||
|
||||
WORKDIR /app
|
||||
@@ -20,7 +47,9 @@ COPY app/ ./app/
|
||||
COPY utils/ ./utils/
|
||||
COPY alembic/ ./alembic/
|
||||
COPY alembic.ini .
|
||||
COPY static/ ./static/
|
||||
|
||||
# Copy built Angular frontend from first stage to static directory
|
||||
COPY --from=frontend-build /frontend/dist/frontend/browser ./static/
|
||||
|
||||
# Create non-root user (Alpine uses adduser instead of useradd)
|
||||
RUN adduser -D -u 1000 appuser && chown -R appuser:appuser /app
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# Multi-stage build for Angular frontend
|
||||
FROM node:24-alpine AS build
|
||||
|
||||
# Accept npm registry as build argument
|
||||
ARG NPM_REGISTRY=https://registry.npmjs.org/
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY frontend/package*.json ./
|
||||
|
||||
# Configure npm registry and regenerate package-lock.json if custom registry is provided
|
||||
RUN if [ "$NPM_REGISTRY" != "https://registry.npmjs.org/" ]; then \
|
||||
echo "Using custom npm registry: $NPM_REGISTRY"; \
|
||||
npm config set registry "$NPM_REGISTRY"; \
|
||||
rm -f package-lock.json; \
|
||||
npm install --package-lock-only; \
|
||||
fi
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy source code
|
||||
COPY frontend/ ./
|
||||
|
||||
# Build for production
|
||||
RUN npm run build:prod
|
||||
|
||||
# Final stage - nginx to serve static files
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy built Angular app to nginx
|
||||
COPY --from=build /app/dist/frontend/browser /usr/share/nginx/html
|
||||
|
||||
# Copy nginx configuration
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Dockerfile for pre-built Angular frontend (air-gapped/restricted environments)
|
||||
#
|
||||
# IMPORTANT: You must build the Angular app BEFORE running docker-compose!
|
||||
# Run this command first: ./build-for-airgap.sh
|
||||
# OR manually: cd frontend && npm install && npm run build:prod
|
||||
#
|
||||
# This Dockerfile expects frontend/dist/frontend/browser to exist
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy pre-built Angular app to nginx
|
||||
# If this step fails, you need to run: ./build-for-airgap.sh
|
||||
COPY frontend/dist/frontend/browser /usr/share/nginx/html
|
||||
|
||||
# Copy nginx configuration
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
26
app/main.py
26
app/main.py
@@ -84,6 +84,32 @@ async def ui_root():
|
||||
}
|
||||
|
||||
|
||||
# Catch-all route for Angular SPA routing - must be last
|
||||
@app.get("/{full_path:path}")
|
||||
async def serve_spa(full_path: str):
|
||||
"""Serve Angular SPA for all non-API routes"""
|
||||
# If it's an API route, it should have been handled by routers above
|
||||
# If it's a static file request, try to serve it
|
||||
if full_path.startswith("static/"):
|
||||
file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), full_path)
|
||||
if os.path.exists(file_path):
|
||||
return FileResponse(file_path)
|
||||
|
||||
# For all other routes (Angular routes), serve index.html
|
||||
index_path = os.path.join(static_dir, "index.html")
|
||||
if os.path.exists(index_path):
|
||||
return FileResponse(index_path)
|
||||
else:
|
||||
return {
|
||||
"message": "Warehouse13 - Enterprise Test Artifact Storage",
|
||||
"version": "1.0.0",
|
||||
"docs": "/docs",
|
||||
"ui": "UI not found. Serving API only.",
|
||||
"deployment_mode": settings.deployment_mode,
|
||||
"storage_backend": settings.storage_backend
|
||||
}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
"""Health check endpoint"""
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "========================================="
|
||||
echo "Building Angular for Air-Gapped Deployment"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
echo "Error: Must run from project root directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if node is installed
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "Error: Node.js is not installed. Please install Node.js 18+ first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if npm is installed
|
||||
if ! command -v npm &> /dev/null; then
|
||||
echo "Error: npm is not installed. Please install npm first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Step 1/3: Installing dependencies..."
|
||||
cd frontend
|
||||
npm install
|
||||
|
||||
echo ""
|
||||
echo "Step 2/3: Building Angular production bundle..."
|
||||
npm run build:prod
|
||||
|
||||
echo ""
|
||||
echo "Step 3/3: Verifying build output..."
|
||||
if [ -d "dist/frontend/browser" ]; then
|
||||
echo "✓ Build successful!"
|
||||
echo "✓ Output: frontend/dist/frontend/browser"
|
||||
ls -lh dist/frontend/browser | head -5
|
||||
else
|
||||
echo "✗ Build failed - output directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd ..
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Build Complete!"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Update docker-compose.yml:"
|
||||
echo " Change: dockerfile: Dockerfile.frontend"
|
||||
echo " To: dockerfile: Dockerfile.frontend.prebuilt"
|
||||
echo ""
|
||||
echo "2. Deploy:"
|
||||
echo " docker-compose up -d --build"
|
||||
echo ""
|
||||
echo "See DEPLOYMENT.md for more details."
|
||||
echo "========================================="
|
||||
@@ -59,20 +59,6 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.frontend.prebuilt
|
||||
ports:
|
||||
- "4200:80"
|
||||
depends_on:
|
||||
- api
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
|
||||
5038
frontend/package-lock.json
generated
5038
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
nginx.conf
36
nginx.conf
@@ -1,36 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Gzip compression
|
||||
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;
|
||||
|
||||
# Angular routes - serve index.html for all routes
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Proxy API requests to backend
|
||||
location /api {
|
||||
proxy_pass http://api:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
@@ -28,17 +28,12 @@ if ! command -v docker-compose &> /dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Step 1: Building Angular frontend locally..."
|
||||
echo "==========================================="
|
||||
./build-for-airgap.sh
|
||||
|
||||
echo ""
|
||||
echo "Step 2: Starting Docker containers..."
|
||||
echo "Step 1: Starting Docker containers..."
|
||||
echo "==========================================="
|
||||
docker-compose up -d --build
|
||||
|
||||
echo ""
|
||||
echo "Step 3: Waiting for services to be ready..."
|
||||
echo "Step 2: Waiting for services to be ready..."
|
||||
sleep 15
|
||||
|
||||
echo ""
|
||||
@@ -46,8 +41,7 @@ echo "========================================="
|
||||
echo "Services are running!"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
echo "Frontend: http://localhost:4200"
|
||||
echo "API: http://localhost:8000"
|
||||
echo "Web UI: http://localhost:8000"
|
||||
echo "API Docs: http://localhost:8000/docs"
|
||||
echo "MinIO Console: http://localhost:9001"
|
||||
echo " Username: minioadmin"
|
||||
|
||||
@@ -41,7 +41,7 @@ echo "========================================="
|
||||
echo "Services are running!"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
echo "API: http://localhost:8000"
|
||||
echo "Web UI: http://localhost:8000"
|
||||
echo "API Docs: http://localhost:8000/docs"
|
||||
echo "MinIO Console: http://localhost:9001"
|
||||
echo " Username: minioadmin"
|
||||
|
||||
Reference in New Issue
Block a user