nothingworry commited on
Commit
62e82b2
·
1 Parent(s): d0d37b9

Fix Docker container startup conflicts and improve error diagnostics

Browse files
Files changed (4) hide show
  1. .dockerignore +30 -0
  2. Dockerfile +34 -0
  3. app.py +9 -5
  4. docker-entrypoint.sh +92 -0
.dockerignore ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python artifacts
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Virtual environments
7
+ .venv/
8
+ venv/
9
+ env/
10
+
11
+ # OS / IDE
12
+ .DS_Store
13
+ Thumbs.db
14
+ .idea/
15
+ .vscode/
16
+
17
+ # Git
18
+ .git/
19
+ .gitignore
20
+
21
+ # Local data and caches
22
+ data/
23
+ logs/
24
+
25
+ # Node / misc large dirs (if ever created)
26
+ node_modules/
27
+
28
+ # Docker build outputs
29
+ *.log
30
+
Dockerfile ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ ENV PYTHONDONTWRITEBYTECODE=1 \
4
+ PYTHONUNBUFFERED=1
5
+
6
+ WORKDIR /app
7
+
8
+ # Install system dependencies
9
+ RUN apt-get update && \
10
+ apt-get install -y --no-install-recommends \
11
+ build-essential \
12
+ curl \
13
+ git && \
14
+ rm -rf /var/lib/apt/lists/*
15
+
16
+ # Install Python dependencies
17
+ COPY requirements.txt /tmp/requirements.txt
18
+ RUN pip install --upgrade pip && \
19
+ pip install --no-cache-dir -r /tmp/requirements.txt
20
+
21
+ # Copy project files
22
+ COPY . .
23
+
24
+ # Ensure entrypoint script is executable
25
+ RUN chmod +x docker-entrypoint.sh
26
+
27
+ EXPOSE 7860 8000 8900
28
+
29
+ ENV API_PORT=8000 \
30
+ MCP_PORT=8900 \
31
+ GRADIO_PORT=7860
32
+
33
+ ENTRYPOINT ["./docker-entrypoint.sh"]
34
+
app.py CHANGED
@@ -2732,13 +2732,17 @@ if __name__ == "__main__":
2732
  import time
2733
  import requests
2734
 
2735
- # For Hugging Face Spaces, bind to 0.0.0.0; for local dev, use 127.0.0.1
2736
- # HF Spaces sets SPACE_ID environment variable
 
2737
  is_hf_space = os.getenv("SPACE_ID") is not None
2738
- server_name = "0.0.0.0" if is_hf_space else "127.0.0.1"
2739
 
2740
- # Start backend services if running in HF Spaces
2741
- if is_hf_space:
 
 
 
2742
  def start_mcp_server():
2743
  """Start MCP server in a background process."""
2744
  try:
 
2732
  import time
2733
  import requests
2734
 
2735
+ # Detect environment
2736
+ # - HF Spaces sets SPACE_ID
2737
+ # - Docker entrypoint script manages services, so don't auto-start here
2738
  is_hf_space = os.getenv("SPACE_ID") is not None
2739
+ is_docker = os.path.exists("/.dockerenv") or os.getenv("DOCKER_CONTAINER") == "1"
2740
 
2741
+ # For Hugging Face Spaces or Docker, bind to 0.0.0.0; for local dev, use 127.0.0.1
2742
+ server_name = "0.0.0.0" if (is_hf_space or is_docker) else "127.0.0.1"
2743
+
2744
+ # Start backend services if running in HF Spaces (but NOT in Docker - entrypoint handles that)
2745
+ if is_hf_space and not is_docker:
2746
  def start_mcp_server():
2747
  """Start MCP server in a background process."""
2748
  try:
docker-entrypoint.sh ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ log() {
5
+ echo "[IntegraChat][$(date -Iseconds)] $*"
6
+ }
7
+
8
+ API_PORT="${API_PORT:-8000}"
9
+ MCP_PORT="${MCP_PORT:-8900}"
10
+ GRADIO_PORT="${GRADIO_PORT:-7860}"
11
+
12
+ export API_PORT MCP_PORT GRADIO_PORT
13
+
14
+ LOG_DIR="/app/logs"
15
+ mkdir -p "${LOG_DIR}"
16
+
17
+ log "Container starting. Python: $(python --version 2>&1)"
18
+ log "API_PORT=${API_PORT}, MCP_PORT=${MCP_PORT}, GRADIO_PORT=${GRADIO_PORT}"
19
+
20
+ cleanup() {
21
+ log "Received termination signal. Stopping services..."
22
+ # Kill child processes
23
+ kill "${MCP_PID}" "${API_PID}" "${GRADIO_PID}" "${TAIL_PID}" 2>/dev/null || true
24
+ wait || true
25
+ log "All services stopped. Exiting."
26
+ }
27
+ trap cleanup SIGTERM SIGINT
28
+
29
+ # Start MCP server
30
+ log "Starting MCP server..."
31
+ python -m backend.mcp_server.server > "${LOG_DIR}/mcp.log" 2>&1 &
32
+ MCP_PID=$!
33
+
34
+ # Give MCP a moment
35
+ sleep 2
36
+
37
+ # Start FastAPI backend
38
+ log "Starting FastAPI backend..."
39
+ uvicorn backend.api.main:app --host 0.0.0.0 --port "${API_PORT}" > "${LOG_DIR}/fastapi.log" 2>&1 &
40
+ API_PID=$!
41
+
42
+ # Check if FastAPI process started
43
+ sleep 2
44
+ if ! kill -0 "${API_PID}" 2>/dev/null; then
45
+ log "ERROR: FastAPI process died immediately. Last 20 lines of log:"
46
+ tail -n 20 "${LOG_DIR}/fastapi.log" || true
47
+ exit 1
48
+ fi
49
+
50
+ # Wait for FastAPI to become healthy
51
+ log "Waiting for FastAPI health endpoint..."
52
+ for attempt in {1..60}; do
53
+ if curl -fsS "http://127.0.0.1:${API_PORT}/health" >/dev/null 2>&1; then
54
+ log "FastAPI backend is healthy."
55
+ break
56
+ fi
57
+ # Check if process is still running
58
+ if ! kill -0 "${API_PID}" 2>/dev/null; then
59
+ log "ERROR: FastAPI process died. Last 20 lines of log:"
60
+ tail -n 20 "${LOG_DIR}/fastapi.log" || true
61
+ exit 1
62
+ fi
63
+ sleep 1
64
+ if [ $((attempt % 10)) -eq 0 ]; then
65
+ log "FastAPI not ready yet (attempt ${attempt}/60). Last 5 lines of log:"
66
+ tail -n 5 "${LOG_DIR}/fastapi.log" || true
67
+ else
68
+ log "FastAPI not ready yet (attempt ${attempt}/60)..."
69
+ fi
70
+ done
71
+
72
+ # Final check
73
+ if ! curl -fsS "http://127.0.0.1:${API_PORT}/health" >/dev/null 2>&1; then
74
+ log "WARNING: FastAPI health check failed after 60 attempts. Last 30 lines of log:"
75
+ tail -n 30 "${LOG_DIR}/fastapi.log" || true
76
+ log "Continuing anyway..."
77
+ fi
78
+
79
+ # Start Gradio UI (foreground)
80
+ log "Starting Gradio UI on port ${GRADIO_PORT}..."
81
+ # Set DOCKER_CONTAINER flag so app.py knows not to auto-start services
82
+ export DOCKER_CONTAINER=1
83
+ python app.py > "${LOG_DIR}/gradio.log" 2>&1 &
84
+ GRADIO_PID=$!
85
+
86
+ log "All services launched. Streaming logs (Ctrl+C to stop)..."
87
+ tail -n 50 -F "${LOG_DIR}/"*.log &
88
+ TAIL_PID=$!
89
+
90
+ wait "${GRADIO_PID}"
91
+ cleanup
92
+