muhammadnoman76 commited on
Commit
2321a58
·
1 Parent(s): a03dbc8
Dockerfile CHANGED
@@ -51,8 +51,8 @@ COPY --from=python-deps /usr/local/bin /usr/local/bin
51
  # Copy backend application code
52
  COPY metsa-backend/ ./
53
 
54
- # Copy built frontend files from the builder stage to static directory
55
- COPY --from=frontend-builder /app/frontend/out ./static
56
 
57
  # Create uploads directory structure
58
  RUN mkdir -p uploads/commercial \
@@ -64,7 +64,7 @@ ENV PORT=8000
64
  ENV APP_NAME="Document Portal API"
65
  ENV APP_VERSION="1.0.0"
66
  ENV DEBUG=True
67
- ENV MONGODB_URL=mongodb://localhost:27017
68
  ENV DATABASE_NAME=document_portal
69
  ENV SECRET_KEY=your-secret-key-here-change-in-production
70
  ENV ALGORITHM=HS256
 
51
  # Copy backend application code
52
  COPY metsa-backend/ ./
53
 
54
+ # Copy built frontend files from the builder stage to the expected location
55
+ COPY --from=frontend-builder /app/frontend/out ./metsa-frontend/out
56
 
57
  # Create uploads directory structure
58
  RUN mkdir -p uploads/commercial \
 
64
  ENV APP_NAME="Document Portal API"
65
  ENV APP_VERSION="1.0.0"
66
  ENV DEBUG=True
67
+ ENV MONGODB_URL=mongodb+srv://lawyerlit11:3uN39xD2C2lGiMyY@cluster0.rqm6zmq.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
68
  ENV DATABASE_NAME=document_portal
69
  ENV SECRET_KEY=your-secret-key-here-change-in-production
70
  ENV ALGORITHM=HS256
README-Docker.md DELETED
@@ -1,46 +0,0 @@
1
- # Metsa App - Docker Setup
2
-
3
- This repository runs the Next.js frontend and FastAPI backend together using a single container image (with docker-compose for convenience).
4
-
5
- ## Prerequisites
6
- - Docker 24+
7
- - Docker Compose plugin (`docker compose`) or Docker Desktop
8
- - Make (optional; Windows users can use Git Bash or WSL)
9
-
10
- ## Quick start
11
-
12
- ```bash
13
- # Build image
14
- make build
15
- # Start
16
- make up
17
- # Tail logs
18
- make logs
19
- # Stop
20
- make down
21
- ```
22
-
23
- Without Make:
24
- ```bash
25
- docker compose build
26
- docker compose up -d
27
- docker compose logs -f --tail=200
28
- ```
29
-
30
- App URLs:
31
- - Frontend: http://localhost:3000
32
- - Backend: http://localhost:8000 (FastAPI docs: http://localhost:8000/docs)
33
-
34
- ## How it works
35
- - Multi-stage Dockerfile builds the Next.js app, then runs both the built Next app and the FastAPI server in the final runtime image.
36
- - A small start.sh launches the backend (Uvicorn) in background and then starts Next.js.
37
- - docker-compose exposes ports 3000 and 8000 and mounts `metsa-backend/uploads` so files persist across restarts.
38
-
39
- ## Customizing
40
- - Frontend API base URL can be overridden via NEXT_PUBLIC_API_URL (defaults to http://localhost:8000/api/v1).
41
- - For production, set proper environment variables in docker-compose.yml and secure the backend settings.
42
-
43
- ## Notes
44
- - This single-container approach is simple for development and small deployments. For production, consider separate services and a reverse proxy.
45
- - Ensure MongoDB is reachable by the backend. Update `metsa-backend/app/config.py` MONGODB_URL or use an external MongoDB service/container.
46
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docker-compose.yml DELETED
@@ -1,43 +0,0 @@
1
- version: '3.8'
2
-
3
- services:
4
- app:
5
- build:
6
- context: .
7
- dockerfile: Dockerfile
8
- ports:
9
- - "8000:8000"
10
- environment:
11
- - NODE_ENV=production
12
- - NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
13
- - DATABASE_URL=mongodb://mongo:27017/metsa
14
- - SECRET_KEY=your-secret-key-change-in-production
15
- - ALGORITHM=HS256
16
- - ACCESS_TOKEN_EXPIRE_MINUTES=30
17
- volumes:
18
- - ./metsa-backend/uploads:/app/metsa-backend/uploads
19
- - ./metsa-backend/.env:/app/metsa-backend/.env
20
- depends_on:
21
- - mongo
22
- networks:
23
- - metsa-network
24
-
25
- mongo:
26
- image: mongo:7.0
27
- ports:
28
- - "27017:27017"
29
- volumes:
30
- - mongo-data:/data/db
31
- environment:
32
- - MONGO_INITDB_ROOT_USERNAME=admin
33
- - MONGO_INITDB_ROOT_PASSWORD=admin123
34
- - MONGO_INITDB_DATABASE=metsa
35
- networks:
36
- - metsa-network
37
-
38
- volumes:
39
- mongo-data:
40
-
41
- networks:
42
- metsa-network:
43
- driver: bridge
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
metsa-backend/.env.example DELETED
@@ -1,25 +0,0 @@
1
- # Application
2
- APP_NAME="Document Portal API"
3
- APP_VERSION="1.0.0"
4
- DEBUG=True
5
-
6
- # MongoDB
7
- MONGODB_URL=mongodb://localhost:27017
8
- DATABASE_NAME=document_portal
9
-
10
- # Security
11
- SECRET_KEY=your-secret-key-here-change-in-production
12
- ALGORITHM=HS256
13
- ACCESS_TOKEN_EXPIRE_MINUTES=1440
14
-
15
- # Email
16
- SMTP_HOST=smtp.gmail.com
17
- SMTP_PORT=587
18
- SMTP_USER=your-email@gmail.com
19
- SMTP_PASSWORD=your-app-password
20
- EMAILS_FROM_EMAIL=noreply@metsa.com
21
- EMAILS_FROM_NAME=Metsa Document Portal
22
-
23
- # File Upload
24
- UPLOAD_DIR=uploads
25
- MAX_FILE_SIZE=10485760
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
metsa-backend/app/config.py CHANGED
@@ -9,7 +9,7 @@ class Settings(BaseModel):
9
  BASE_URL: str = "http://localhost:8000"
10
 
11
  # MongoDB
12
- MONGODB_URL: str = "mongodb://localhost:27017"
13
  DATABASE_NAME: str = "document_portal"
14
 
15
  # Security
 
9
  BASE_URL: str = "http://localhost:8000"
10
 
11
  # MongoDB
12
+ MONGODB_URL: str = "mongodb+srv://lawyerlit11:3uN39xD2C2lGiMyY@cluster0.rqm6zmq.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
13
  DATABASE_NAME: str = "document_portal"
14
 
15
  # Security
metsa-backend/app/main.py CHANGED
@@ -61,47 +61,56 @@ app.add_middleware(
61
  allow_headers=["*"],
62
  )
63
 
64
- # Include routers
65
  app.include_router(auth.router, prefix="/api/v1")
66
  app.include_router(users.router, prefix="/api/v1")
67
  app.include_router(documents.router, prefix="/api/v1")
68
  app.include_router(notifications.router, prefix="/api/v1")
69
 
 
 
 
 
 
 
 
 
 
70
  @app.get("/")
71
  async def root():
 
 
 
72
  return {
73
  "message": "Welcome to Metsa Document Portal API",
74
  "version": settings.APP_VERSION,
75
  "docs": "/docs"
76
  }
77
 
78
- # Serve Next.js static export (built assets)
79
- FRONTEND_DIR = Path(__file__).resolve().parents[2] / "metsa-frontend" / "out"
80
- INDEX_FILE = FRONTEND_DIR / "index.html"
81
-
82
  @app.get("/{full_path:path}")
83
  async def serve_frontend(full_path: str):
84
  # API routes are already handled by routers with /api/v1 prefix
85
  # This catches everything else and serves static files from Next.js export
86
  target = (FRONTEND_DIR / full_path).resolve()
87
  try:
88
- # Prevent path traversal
89
- target.relative_to(FRONTEND_DIR)
90
  except Exception:
91
- raise HTTPException(status_code=404, detail="Not Found")
 
 
 
92
 
93
  if target.is_dir():
94
  index_in_dir = target / "index.html"
95
  if index_in_dir.exists():
96
- return FileResponse(index_in_dir)
 
97
  if target.exists() and target.is_file():
98
  return FileResponse(target)
 
99
  # Fallback to top-level index.html for SPA routes
100
  if INDEX_FILE.exists():
101
- return FileResponse(INDEX_FILE)
 
102
  raise HTTPException(status_code=404, detail="Frontend not built")
103
-
104
-
105
- @app.get("/health")
106
- async def health_check():
107
- return {"status": "healthy"}
 
61
  allow_headers=["*"],
62
  )
63
 
64
+ # Include routers (API routes)
65
  app.include_router(auth.router, prefix="/api/v1")
66
  app.include_router(users.router, prefix="/api/v1")
67
  app.include_router(documents.router, prefix="/api/v1")
68
  app.include_router(notifications.router, prefix="/api/v1")
69
 
70
+ # Health check endpoint (before catch-all)
71
+ @app.get("/health")
72
+ async def health_check():
73
+ return {"status": "healthy"}
74
+
75
+ # Serve Next.js static export (built assets)
76
+ FRONTEND_DIR = Path(__file__).resolve().parents[1] / "metsa-frontend" / "out"
77
+ INDEX_FILE = FRONTEND_DIR / "index.html"
78
+
79
  @app.get("/")
80
  async def root():
81
+ # Serve the frontend index.html for the root route
82
+ if INDEX_FILE.exists():
83
+ return FileResponse(INDEX_FILE, media_type="text/html")
84
  return {
85
  "message": "Welcome to Metsa Document Portal API",
86
  "version": settings.APP_VERSION,
87
  "docs": "/docs"
88
  }
89
 
 
 
 
 
90
  @app.get("/{full_path:path}")
91
  async def serve_frontend(full_path: str):
92
  # API routes are already handled by routers with /api/v1 prefix
93
  # This catches everything else and serves static files from Next.js export
94
  target = (FRONTEND_DIR / full_path).resolve()
95
  try:
96
+ # Prevent path traversal
97
+ target.relative_to(FRONTEND_DIR)
98
  except Exception:
99
+ # Fallback to index.html for SPA routes
100
+ if INDEX_FILE.exists():
101
+ return FileResponse(INDEX_FILE, media_type="text/html")
102
+ raise HTTPException(status_code=404, detail="Not Found")
103
 
104
  if target.is_dir():
105
  index_in_dir = target / "index.html"
106
  if index_in_dir.exists():
107
+ return FileResponse(index_in_dir, media_type="text/html")
108
+
109
  if target.exists() and target.is_file():
110
  return FileResponse(target)
111
+
112
  # Fallback to top-level index.html for SPA routes
113
  if INDEX_FILE.exists():
114
+ return FileResponse(INDEX_FILE, media_type="text/html")
115
+
116
  raise HTTPException(status_code=404, detail="Frontend not built")