TheDeepDas commited on
Commit
3902e25
Β·
1 Parent(s): 95b078e
Files changed (4) hide show
  1. Dockerfile +11 -3
  2. Dockerfile.simple +38 -0
  3. FIX_PERMISSIONS.md +56 -0
  4. app/services/incidents.py +28 -2
Dockerfile CHANGED
@@ -9,6 +9,9 @@ ENV PYTHONDONTWRITEBYTECODE=1
9
  ENV PYTHONUNBUFFERED=1
10
  ENV PORT=7860
11
 
 
 
 
12
  # Install system dependencies
13
  RUN apt-get update && apt-get install -y \
14
  build-essential \
@@ -25,11 +28,16 @@ RUN pip install --no-cache-dir -r requirements.txt
25
  # Copy the application code
26
  COPY . .
27
 
 
 
 
 
 
28
  # Make startup script executable
29
- RUN chmod +x start-hf.sh
30
 
31
- # Create models directory if it doesn't exist
32
- RUN mkdir -p models
33
 
34
  # Expose port 7860 (Hugging Face Spaces default)
35
  EXPOSE 7860
 
9
  ENV PYTHONUNBUFFERED=1
10
  ENV PORT=7860
11
 
12
+ # Create a non-root user for security
13
+ RUN useradd --create-home --shell /bin/bash app
14
+
15
  # Install system dependencies
16
  RUN apt-get update && apt-get install -y \
17
  build-essential \
 
28
  # Copy the application code
29
  COPY . .
30
 
31
+ # Create necessary directories with proper permissions
32
+ RUN mkdir -p models app/uploads /tmp/uploads && \
33
+ chown -R app:app /app /tmp/uploads && \
34
+ chmod -R 755 /app /tmp/uploads
35
+
36
  # Make startup script executable
37
+ RUN chmod +x start-hf.sh && chown app:app start-hf.sh
38
 
39
+ # Switch to non-root user
40
+ USER app
41
 
42
  # Expose port 7860 (Hugging Face Spaces default)
43
  EXPOSE 7860
Dockerfile.simple ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Simplified Dockerfile for Hugging Face Spaces
2
+ # Use this if the current one has permission issues
3
+
4
+ FROM python:3.11-slim
5
+
6
+ WORKDIR /app
7
+
8
+ # Environment variables
9
+ ENV PYTHONDONTWRITEBYTECODE=1
10
+ ENV PYTHONUNBUFFERED=1
11
+ ENV PORT=7860
12
+
13
+ # Install system dependencies
14
+ RUN apt-get update && apt-get install -y \
15
+ build-essential \
16
+ curl \
17
+ && rm -rf /var/lib/apt/lists/*
18
+
19
+ # Copy and install requirements
20
+ COPY requirements.txt .
21
+ RUN pip install --no-cache-dir --upgrade pip && \
22
+ pip install --no-cache-dir -r requirements.txt
23
+
24
+ # Copy application
25
+ COPY . .
26
+
27
+ # Create uploads directory in tmp (writable location)
28
+ RUN mkdir -p /tmp/uploads && chmod 777 /tmp/uploads
29
+
30
+ # Expose port
31
+ EXPOSE 7860
32
+
33
+ # Simple health check
34
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
35
+ CMD curl -f http://localhost:7860/health || exit 1
36
+
37
+ # Direct uvicorn command (no shell script)
38
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
FIX_PERMISSIONS.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # πŸ”§ Permission Error Fix for Hugging Face Spaces
2
+
3
+ ## ❌ Problem
4
+ ```
5
+ PermissionError: [Errno 13] Permission denied: '/app/app/uploads'
6
+ ```
7
+
8
+ ## βœ… Solutions Applied
9
+
10
+ ### 1. **Updated Dockerfile**
11
+ - Added non-root user for better security
12
+ - Created upload directories with proper permissions
13
+ - Added fallback to `/tmp/uploads` directory
14
+
15
+ ### 2. **Updated incidents.py Service**
16
+ - Multiple fallback directory locations
17
+ - Graceful error handling for directory creation
18
+ - Logs directory creation attempts
19
+
20
+ ### 3. **Alternative Simple Dockerfile**
21
+ Created `Dockerfile.simple` as backup if main one fails:
22
+ - Minimal setup without user switching
23
+ - Direct uvicorn command (no shell script)
24
+ - Uses `/tmp/uploads` (guaranteed writable)
25
+
26
+ ## πŸš€ Deploy Options
27
+
28
+ ### **Option 1: Use Updated Dockerfile (Recommended)**
29
+ The main `Dockerfile` now handles permissions properly.
30
+
31
+ ### **Option 2: Use Simple Dockerfile**
32
+ If still having issues, rename files:
33
+ ```bash
34
+ mv Dockerfile Dockerfile.backup
35
+ mv Dockerfile.simple Dockerfile
36
+ ```
37
+
38
+ ### **Option 3: Manual Environment Variables**
39
+ Set in HF Spaces environment:
40
+ ```
41
+ UPLOAD_DIR=/tmp/uploads
42
+ ```
43
+
44
+ ## 🎯 Expected Result
45
+ - App should start successfully
46
+ - Upload directory will be created in `/tmp/uploads` if main location fails
47
+ - All functionality preserved with fallback handling
48
+
49
+ ## πŸ“Š Commit & Push
50
+ ```bash
51
+ git add .
52
+ git commit -m "Fix permission errors for HF Spaces deployment"
53
+ git push
54
+ ```
55
+
56
+ The deployment should now work on Hugging Face Spaces! πŸŽ‰
app/services/incidents.py CHANGED
@@ -1,12 +1,38 @@
1
  from pathlib import Path
2
  from typing import Optional
3
  from uuid import uuid4
 
4
 
5
  from ..database import get_collection
6
 
 
 
7
  INCIDENTS_COLLECTION = "incidents"
8
- UPLOAD_DIR = Path(__file__).resolve().parent.parent / "uploads"
9
- UPLOAD_DIR.mkdir(exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
 
12
  async def save_incident_document(document: dict) -> dict:
 
1
  from pathlib import Path
2
  from typing import Optional
3
  from uuid import uuid4
4
+ import logging
5
 
6
  from ..database import get_collection
7
 
8
+ logger = logging.getLogger(__name__)
9
+
10
  INCIDENTS_COLLECTION = "incidents"
11
+
12
+ # Try multiple upload directory locations
13
+ upload_paths = [
14
+ Path(__file__).resolve().parent.parent / "uploads",
15
+ Path("/tmp/uploads"),
16
+ Path("/app/uploads")
17
+ ]
18
+
19
+ UPLOAD_DIR = None
20
+ for path in upload_paths:
21
+ try:
22
+ path.mkdir(exist_ok=True, parents=True)
23
+ UPLOAD_DIR = path
24
+ logger.info(f"Upload directory ready: {UPLOAD_DIR}")
25
+ break
26
+ except PermissionError:
27
+ logger.warning(f"Cannot create upload directory at {path}")
28
+ continue
29
+ except Exception as e:
30
+ logger.warning(f"Error creating upload directory at {path}: {e}")
31
+ continue
32
+
33
+ if UPLOAD_DIR is None:
34
+ logger.error("Could not create any upload directory")
35
+ UPLOAD_DIR = Path("/tmp") # Fallback to /tmp
36
 
37
 
38
  async def save_incident_document(document: dict) -> dict: