jameszokah commited on
Commit
f08f6c6
·
1 Parent(s): 6712559

Refactor Dockerfile and add run script: streamline multi-stage build, set up application structure, and create a new run script for environment initialization and database migration; update migrations/env.py for improved error handling during model import.

Browse files
Files changed (3) hide show
  1. Dockerfile +25 -73
  2. migrations/env.py +11 -3
  3. scripts/run.sh +45 -0
Dockerfile CHANGED
@@ -1,95 +1,47 @@
1
- # Multi-stage build for authenticated model downloads
2
- FROM python:3.10-slim AS model-downloader
3
- # Install huggingface-cli
4
- RUN pip install huggingface_hub
5
- # Set working directory
6
- WORKDIR /model-downloader
7
- # Create directory for downloaded models
8
- RUN mkdir -p /model-downloader/models
9
- # This will run when building the image
10
- # You'll need to pass your Hugging Face token at build time
11
- ARG HF_TOKEN
12
- ENV HF_TOKEN=${HF_TOKEN}
13
- # Login and download model
14
- RUN if [ -n "$HF_TOKEN" ]; then \
15
- huggingface-cli login --token ${HF_TOKEN}; \
16
- huggingface-cli download sesame/csm-1b ckpt.pt --local-dir /model-downloader/models; \
17
- else echo "No HF_TOKEN provided, model download will be skipped"; fi
18
-
19
- # Now for the main application stage
20
  FROM python:3.10-slim
21
 
 
 
 
 
 
 
 
 
 
22
  # Install system dependencies
23
  RUN apt-get update && apt-get install -y \
24
  build-essential \
25
- ffmpeg \
26
- git \
27
  netcat-openbsd \
 
28
  && rm -rf /var/lib/apt/lists/*
29
 
30
- # Set working directory
31
- WORKDIR /app
 
32
 
33
- # Install Python dependencies
34
  COPY requirements.txt .
35
- RUN pip install --no-cache-dir -r requirements.txt
36
-
37
- # Install additional dependencies for database and storage
38
- RUN pip install --no-cache-dir \
39
- sqlalchemy==2.0.27 \
40
- aiofiles==23.2.1 \
41
- psycopg2-binary==2.9.9 \
42
- alembic==1.13.1
43
-
44
- # Create necessary directories with proper package structure
45
- RUN mkdir -p /app/storage/audio \
46
- /app/storage/text \
47
- /app/models \
48
- /app/tokenizers \
49
- /app/voice_memories \
50
- /app/voice_references \
51
- /app/voice_profiles \
52
- /app/cloned_voices \
53
- /app/audio_cache \
54
- /app/static \
55
- /app/logs \
56
- /app/migrations/versions \
57
- /app/app/models
58
 
59
- # Create Python package structure
60
- RUN touch /app/app/__init__.py \
61
- /app/app/models/__init__.py
62
-
63
- # Copy the model from the model-downloader stage
64
- COPY --from=model-downloader /model-downloader/models /app/models
65
 
66
  # Copy application code
67
  COPY . .
68
 
69
- # Copy and set up entrypoint script
70
- COPY docker-entrypoint.sh /usr/local/bin/
71
- RUN chmod +x /usr/local/bin/docker-entrypoint.sh
72
-
73
- # Create volume mount points
74
- VOLUME ["/app/storage", "/app/models", "/app/logs"]
75
-
76
- # Set environment variables
77
- ENV PYTHONPATH=/app \
78
- DATABASE_URL=sqlite:///app/storage/audiobooks.db \
79
- STORAGE_PATH=/app/storage
80
 
81
- # Set permissions for all directories
82
- RUN chown -R nobody:nogroup /app && \
83
- chmod -R 755 /app && \
84
- # Make migrations directory writable
85
- chmod -R 777 /app/migrations && \
86
- chmod -R 777 /app/storage
87
 
88
- # Switch to non-root user
89
- USER nobody
90
 
91
  # Expose port
92
  EXPOSE 7860
93
 
94
  # Set the entrypoint
95
- ENTRYPOINT ["docker-entrypoint.sh"]
 
1
+ # Use Python 3.10 as the base image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  FROM python:3.10-slim
3
 
4
+ # Set environment variables
5
+ ENV PYTHONUNBUFFERED=1 \
6
+ PYTHONDONTWRITEBYTECODE=1 \
7
+ PIP_NO_CACHE_DIR=1 \
8
+ PIP_DISABLE_PIP_VERSION_CHECK=1
9
+
10
+ # Create and set working directory
11
+ WORKDIR /app
12
+
13
  # Install system dependencies
14
  RUN apt-get update && apt-get install -y \
15
  build-essential \
 
 
16
  netcat-openbsd \
17
+ ffmpeg \
18
  && rm -rf /var/lib/apt/lists/*
19
 
20
+ # Create app user
21
+ RUN useradd -m -u 1000 app && \
22
+ chown -R app:app /app
23
 
24
+ # Copy requirements file
25
  COPY requirements.txt .
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ # Install Python dependencies
28
+ RUN pip install --no-cache-dir -r requirements.txt
 
 
 
 
29
 
30
  # Copy application code
31
  COPY . .
32
 
33
+ # Create necessary directories
34
+ RUN mkdir -p /app/storage/audio /app/storage/text /app/storage/temp && \
35
+ chown -R app:app /app/storage
 
 
 
 
 
 
 
 
36
 
37
+ # Switch to app user
38
+ USER app
 
 
 
 
39
 
40
+ # Make run script executable
41
+ RUN chmod +x scripts/run.sh
42
 
43
  # Expose port
44
  EXPOSE 7860
45
 
46
  # Set the entrypoint
47
+ ENTRYPOINT ["/app/scripts/run.sh"]
migrations/env.py CHANGED
@@ -7,11 +7,19 @@ from sqlalchemy import pool
7
 
8
  from alembic import context
9
 
10
- # Add the application root directory to the Python path
11
- sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
12
 
13
  # Import your models here
14
- from app.models.database import Base
 
 
 
 
 
 
15
 
16
  # this is the Alembic Config object
17
  config = context.config
 
7
 
8
  from alembic import context
9
 
10
+ # Add the application directory to the Python path
11
+ app_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
12
+ if app_dir not in sys.path:
13
+ sys.path.insert(0, app_dir)
14
 
15
  # Import your models here
16
+ try:
17
+ from app.models.database import Base
18
+ except ImportError as e:
19
+ raise Exception(
20
+ f"Failed to import models. PYTHONPATH: {os.environ.get('PYTHONPATH')}, "
21
+ f"sys.path: {sys.path}, Error: {str(e)}"
22
+ )
23
 
24
  # this is the Alembic Config object
25
  config = context.config
scripts/run.sh ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Initialize environment variables with defaults if not set
5
+ export PORT=${PORT:-7860}
6
+ export HOST=${HOST:-"0.0.0.0"}
7
+ export WORKERS=${WORKERS:-1}
8
+ export LOG_LEVEL=${LOG_LEVEL:-"info"}
9
+
10
+ # Wait for database to be ready (if using external database)
11
+ if [ ! -z "$DATABASE_URL" ] && [[ "$DATABASE_URL" != sqlite* ]]; then
12
+ host=$(echo $DATABASE_URL | awk -F[@//] '{print $4}' | cut -d: -f1)
13
+ port=$(echo $DATABASE_URL | awk -F[@//] '{print $4}' | cut -d: -f2 | cut -d/ -f1)
14
+
15
+ echo "Waiting for database at $host:$port..."
16
+ while ! nc -z $host $port; do
17
+ sleep 1
18
+ done
19
+ echo "Database is ready!"
20
+ fi
21
+
22
+ # Run database migrations
23
+ echo "Running database migrations..."
24
+ alembic upgrade head
25
+
26
+ # Create necessary directories if they don't exist
27
+ mkdir -p /app/storage/audio
28
+ mkdir -p /app/storage/text
29
+ mkdir -p /app/storage/temp
30
+
31
+ # Set proper permissions
32
+ chown -R app:app /app/storage
33
+
34
+ echo "Starting CSM-1B TTS API server..."
35
+ echo "Host: $HOST"
36
+ echo "Port: $PORT"
37
+ echo "Workers: $WORKERS"
38
+ echo "Log Level: $LOG_LEVEL"
39
+
40
+ # Start the FastAPI application using uvicorn
41
+ exec uvicorn app.main:app \
42
+ --host "$HOST" \
43
+ --port "$PORT" \
44
+ --workers "$WORKERS" \
45
+ --log-level "$LOG_LEVEL"