Gianpaolo Macario
commited on
Commit
·
e21102a
1
Parent(s):
d229ac5
feat: first shot at dockerizing app.py
Browse files- .dockerignore +16 -0
- Dockerfile +51 -0
- app.py +3 -1
- docker-compose.yaml +19 -0
- entrypoint.sh +12 -0
- env.example +3 -0
- 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 |
-
|
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")
|