Gianpaolo Macario commited on
Commit
e21102a
·
1 Parent(s): d229ac5

feat: first shot at dockerizing app.py

Browse files
Files changed (7) hide show
  1. .dockerignore +16 -0
  2. Dockerfile +51 -0
  3. app.py +3 -1
  4. docker-compose.yaml +19 -0
  5. entrypoint.sh +12 -0
  6. env.example +3 -0
  7. flux.py +21 -3
.dockerignore ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ .env
7
+ .env.*
8
+ *.sqlite
9
+ *.db
10
+ output/
11
+ .git/
12
+ .gitignore
13
+ .dockerignore
14
+ Dockerfile
15
+ *.md
16
+ !README.md
Dockerfile ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Compile stage: install build dependencies
2
+ FROM python:3.12-slim AS builder
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install build dependencies
8
+ RUN apt-get update && \
9
+ apt-get install -y --no-install-recommends \
10
+ build-essential \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ # Install Python dependencies
14
+ COPY requirements.txt .
15
+ RUN python -m pip install --upgrade pip && \
16
+ python -m pip install --no-cache-dir wheel && \
17
+ pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt
18
+
19
+ # Final stage: copy only necessary files
20
+ FROM python:3.12-slim
21
+
22
+ WORKDIR /app
23
+
24
+ # Copy wheels from builder stage
25
+ COPY --from=builder /app/wheels /wheels
26
+
27
+ # Install Python packages from wheels
28
+ RUN pip install --no-cache /wheels/*
29
+
30
+ # Copy application files
31
+ COPY app.py flux.py stablediffusion.py ./
32
+ COPY pyproject.toml README.md ./
33
+
34
+ # Create directories for temporary files
35
+ RUN mkdir -p /tmp/flux /tmp/flux2 && \
36
+ chmod 777 /tmp/flux /tmp/flux2
37
+
38
+ # Set environment variables
39
+ ENV PYTHONUNBUFFERED=1
40
+ ENV PYTHONDONTWRITEBYTECODE=1
41
+ ENV PYTHONPATH=/app
42
+
43
+ # Copy and set permissions for entrypoint script
44
+ COPY entrypoint.sh .
45
+ RUN chmod +x entrypoint.sh
46
+
47
+ # Expose the port that Gradio will run on
48
+ EXPOSE 7860
49
+
50
+ # Command to run the application
51
+ ENTRYPOINT ["./entrypoint.sh"]
app.py CHANGED
@@ -236,6 +236,8 @@ with gr.Blocks() as demo:
236
  demo.launch(
237
  mcp_server=True,
238
  share=True,
239
- ssr_mode=False)
 
 
240
 
241
  # EOF
 
236
  demo.launch(
237
  mcp_server=True,
238
  share=True,
239
+ ssr_mode=False,
240
+ server_name="0.0.0.0", # Listen on all interfaces
241
+ server_port=7860) # Use the port we exposed in Dockerfile
242
 
243
  # EOF
docker-compose.yaml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ simple-calculator:
5
+ build: .
6
+ ports:
7
+ - "7860:7860"
8
+ environment:
9
+ - PYTHONUNBUFFERED=1
10
+ # Add your Modal credentials here or use .env file
11
+ - MODAL_TOKEN_ID=${MODAL_TOKEN_ID:-}
12
+ - MODAL_TOKEN_SECRET=${MODAL_TOKEN_SECRET:-}
13
+ volumes:
14
+ # Mount the Modal config directory to persist credentials
15
+ - modal-config:/root/.modal
16
+ restart: unless-stopped
17
+
18
+ volumes:
19
+ modal-config: # Named volume for Modal configuration
entrypoint.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Create Modal config directory
4
+ mkdir -p ~/.modal
5
+
6
+ # Write Modal token configuration if provided
7
+ if [ ! -z "$MODAL_TOKEN_ID" ] && [ ! -z "$MODAL_TOKEN_SECRET" ]; then
8
+ echo "{\"token_id\":\"$MODAL_TOKEN_ID\",\"token_secret\":\"$MODAL_TOKEN_SECRET\"}" > ~/.modal/config.json
9
+ fi
10
+
11
+ # Start the application
12
+ exec python app.py
env.example ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # Copy this file to .env and fill in your Modal credentials
2
+ MODAL_TOKEN_ID=your_modal_token_id_here
3
+ MODAL_TOKEN_SECRET=your_modal_token_secret_here
flux.py CHANGED
@@ -2,13 +2,27 @@
2
  #
3
  # See https://modal.com/docs/examples/flux
4
 
5
- # Setting up the image and dependencies
6
-
7
  import time
8
  from io import BytesIO
9
  from pathlib import Path
10
  import modal
11
- import modal.running_app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  # We’ll make use of the full CUDA toolkit in this example, so we’ll build our container image
14
  # off of the nvidia/cuda base.
@@ -284,6 +298,10 @@ def generate_image2(prompt: str):
284
  """
285
 
286
  print("DEBUG: generate_image2 called with prompt:", prompt)
 
 
 
 
287
 
288
  if prompt is None or prompt.strip() == "A portrait of a handsome software developer":
289
  print("DEBUG: Returning hardcoded image URL for default prompt")
 
2
  #
3
  # See https://modal.com/docs/examples/flux
4
 
5
+ import os
6
+ import sys
7
  import time
8
  from io import BytesIO
9
  from pathlib import Path
10
  import modal
11
+ # import modal.running_app
12
+
13
+ # Check for Modal credentials
14
+ MODAL_TOKEN_ID = os.getenv('MODAL_TOKEN_ID')
15
+ MODAL_TOKEN_SECRET = os.getenv('MODAL_TOKEN_SECRET')
16
+
17
+ if not MODAL_TOKEN_ID or not MODAL_TOKEN_SECRET:
18
+ print("WARNING: Modal credentials not found. Image generation will return placeholder images.", file=sys.stderr)
19
+ MODAL_AVAILABLE = False
20
+ else:
21
+ try:
22
+ MODAL_AVAILABLE = True
23
+ except ImportError:
24
+ print("WARNING: Modal package not available. Image generation will return placeholder images.", file=sys.stderr)
25
+ MODAL_AVAILABLE = False
26
 
27
  # We’ll make use of the full CUDA toolkit in this example, so we’ll build our container image
28
  # off of the nvidia/cuda base.
 
298
  """
299
 
300
  print("DEBUG: generate_image2 called with prompt:", prompt)
301
+
302
+ if not MODAL_AVAILABLE:
303
+ print("DEBUG: Modal not available, returning placeholder image")
304
+ return generate_image1(prompt)
305
 
306
  if prompt is None or prompt.strip() == "A portrait of a handsome software developer":
307
  print("DEBUG: Returning hardcoded image URL for default prompt")