# ============================================================================== # MERICA Data Lakehouse — Clean Release Appliance Dockerfile # ============================================================================== # Multi-stage Dockerfile packaging Vite React Frontend, FastAPI Modular Backend, # Nginx Reverse Proxy, and Supervisord into a single, decoupled appliance image. # # Build Command: # docker build -t registry.sicabe.com/merica:1.0.0 . # ============================================================================== # ------------------------------------------------------------------------------ # Stage 1: Build Frontend Assets # ------------------------------------------------------------------------------ FROM node:20-alpine AS frontend-builder WORKDIR /frontend # Install dependencies and build static bundle COPY frontend/package*.json ./ RUN npm install --legacy-peer-deps COPY frontend/ ./ RUN npm run build # ------------------------------------------------------------------------------ # Stage 2: MERICA Clean Appliance Runtime # ------------------------------------------------------------------------------ FROM python:3.11-slim AS appliance LABEL maintainer="BPKP Data Lakehouse Team " LABEL description="MERICA Data Lakehouse - Production Appliance Image" LABEL version="1.0.0" # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ nginx \ supervisor \ curl \ ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Install Python dependencies COPY backend/requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt # Copy Backend application code COPY backend/app ./app # Copy Built Frontend artifacts to Nginx docroot COPY --from=frontend-builder /frontend/dist /usr/share/nginx/html # Setup Nginx, Supervisord, and Entrypoint RUN mkdir -p /etc/nginx/conf.d /etc/supervisor/conf.d /var/log/supervisor /app/configs /app/storage /app/data /app/merica-pipelines/configs /app/merica-pipelines/metadata /app/merica-pipelines/dbt # Nginx Single-Port Reverse Proxy Configuration RUN cat <<'EOF' > /etc/nginx/conf.d/default.conf server { listen 80; server_name localhost; # Frontend Static Assets location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } # Internal Loopback Proxy to FastAPI (127.0.0.1:8000) location /api/ { proxy_pass http://127.0.0.1:8000/api/; 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; proxy_connect_timeout 60s; proxy_read_timeout 120s; # WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # OpenAPI Documentation location /docs { proxy_pass http://127.0.0.1:8000/docs; } location /openapi.json { proxy_pass http://127.0.0.1:8000/openapi.json; } } EOF RUN rm -f /etc/nginx/sites-enabled/default # Supervisord Configuration (Dual Daemon: Nginx + Uvicorn) RUN cat <<'EOF' > /etc/supervisor/conf.d/supervisord.conf [supervisord] nodaemon=true logfile=/var/log/supervisor/supervisord.log pidfile=/var/run/supervisord.pid [program:nginx] command=/usr/sbin/nginx -g "daemon off;" autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:uvicorn] directory=/app command=python -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2 autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 EOF # Entrypoint script RUN cat <<'EOF' > /entrypoint.sh #!/bin/bash set -e echo "🚀 Starting MERICA Appliance..." exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf EOF RUN chmod +x /entrypoint.sh EXPOSE 80 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD curl -f http://127.0.0.1/api/v1/health || exit 1 ENTRYPOINT ["/entrypoint.sh"]