feat(Dockerfile): add root multi-stage Dockerfile for Dokploy

- Stage 1 (node:20): builds Vue.js frontend to /app/dist
- Stage 2 (python:3.12): FastAPI serves API + static files
- main.py: serve Vue.js dist via StaticFiles if /app/dist exists
- Removes GET / route (replaced by frontend index.html)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-04 07:46:32 +00:00
parent b9f994cf8d
commit 99d0c66626
2 changed files with 25 additions and 6 deletions

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
FROM node:20-alpine AS frontend-builder
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
FROM python:3.12-slim
WORKDIR /app
COPY backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY backend/ .
COPY --from=frontend-builder /app/frontend/dist /app/dist
RUN mkdir -p uploads
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -1,6 +1,9 @@
"""FastAPI application entry point.""" """FastAPI application entry point."""
import os
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 app.api.attachments import router as attachments_router from app.api.attachments import router as attachments_router
from app.api.audit_log import router as audit_log_router from app.api.audit_log import router as audit_log_router
@@ -64,13 +67,13 @@ app.include_router(organizations_admin_router, prefix="/api")
app.include_router(public_router, prefix="/api") app.include_router(public_router, prefix="/api")
@app.get("/")
def root() -> dict[str, str]:
"""Root endpoint."""
return {"message": "Space Booking API"}
@app.get("/health") @app.get("/health")
def health() -> dict[str, str]: def health() -> dict[str, str]:
"""Health check endpoint.""" """Health check endpoint."""
return {"status": "ok"} return {"status": "ok"}
# Serve Vue.js frontend in production (when /app/dist exists)
_dist_dir = os.path.join(os.path.dirname(__file__), "..", "..", "dist")
if os.path.isdir(_dist_dir):
app.mount("/", StaticFiles(directory=_dist_dir, html=True), name="static")