Rizwan9 commited on
Commit
48c5931
·
verified ·
1 Parent(s): 7903ae6

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +15 -92
Dockerfile CHANGED
@@ -1,98 +1,21 @@
1
- from flask import Flask, request, jsonify, make_response
2
- import joblib, pandas as pd, numpy as np, os, sys, time
3
 
4
- app = Flask(__name__)
 
 
5
 
6
- # -----------------------------
7
- # Config & Model Loading
8
- # -----------------------------
9
- MODEL_PATH = os.getenv("MODEL_PATH", "best_model_random_forest.joblib")
10
- PORT = int(os.getenv("PORT", "5000"))
11
 
12
- print(f"==> [BOOT] Starting Flask app on port {PORT}")
13
- print(f"==> [BOOT] MODEL_PATH={MODEL_PATH}", flush=True)
 
14
 
15
- def load_pipeline(path: str):
16
- start = time.time()
17
- if not os.path.exists(path):
18
- raise FileNotFoundError(f"Model file not found: {path}")
19
- print(f"==> [LOAD] Loading model from {path} ...", flush=True)
20
- model_obj = joblib.load(path)
21
- if isinstance(model_obj, dict) and "pipeline" in model_obj:
22
- pipe = model_obj["pipeline"]
23
- print("==> [LOAD] Loaded dict bundle with 'pipeline'", flush=True)
24
- else:
25
- pipe = model_obj
26
- print("==> [LOAD] Loaded pipeline object", flush=True)
27
- print(f"==> [LOAD] Model load complete in {time.time()-start:.2f}s", flush=True)
28
- return pipe
29
 
30
- try:
31
- pipe = load_pipeline(MODEL_PATH)
32
- MODEL_READY, LOAD_ERROR = True, None
33
- except Exception as e:
34
- print(f"==> [ERROR] Model load failed: {e}", file=sys.stderr, flush=True)
35
- pipe, MODEL_READY, LOAD_ERROR = None, False, str(e)
36
 
37
- # -----------------------------
38
- # Basic CORS (no external deps)
39
- # -----------------------------
40
- @app.after_request
41
- def add_cors_headers(resp):
42
- resp.headers["Access-Control-Allow-Origin"] = "*"
43
- resp.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization"
44
- resp.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
45
- return resp
46
-
47
- # -----------------------------
48
- # Health & Root
49
- # -----------------------------
50
- @app.get("/")
51
- def root():
52
- return jsonify({
53
- "service": "SuperKart Sales Forecast API",
54
- "health": "/health",
55
- "predict": "/predict",
56
- "model_path": MODEL_PATH
57
- })
58
-
59
- @app.get("/health")
60
- def health():
61
- if MODEL_READY:
62
- return jsonify({"status": "ok", "model_path": MODEL_PATH}), 200
63
- return jsonify({"status": "error", "error": LOAD_ERROR, "model_path": MODEL_PATH}), 500
64
-
65
- # -----------------------------
66
- # Prediction
67
- # -----------------------------
68
- @app.route("/predict", methods=["OPTIONS"])
69
- def predict_options():
70
- return make_response(("", 204))
71
-
72
- @app.post("/predict")
73
- def predict():
74
- if not MODEL_READY or pipe is None:
75
- return jsonify({"error": "Model not loaded", "details": LOAD_ERROR}), 503
76
-
77
- try:
78
- data = request.get_json(force=True)
79
- if isinstance(data, dict):
80
- df = pd.DataFrame([data])
81
- elif isinstance(data, list):
82
- df = pd.DataFrame(data)
83
- else:
84
- return jsonify({"error": "Invalid input. Must be JSON object or list of objects."}), 400
85
-
86
- preds = pipe.predict(df)
87
- preds = [float(p) if isinstance(p, (np.floating, float, int)) else p for p in preds]
88
- return jsonify({"predictions": preds})
89
-
90
- except Exception as e:
91
- return jsonify({"error": "Prediction failed", "details": str(e)}), 500
92
-
93
- # -----------------------------
94
- # Entry Point
95
- # -----------------------------
96
- if __name__ == "__main__":
97
- print("==> [RUN] Flask dev server starting...", flush=True)
98
- app.run(host="0.0.0.0", port=PORT)
 
1
+ FROM python:3.10-slim
 
2
 
3
+ # Prevent buffering & control thread usage
4
+ ENV PYTHONUNBUFFERED=1
5
+ ENV OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 MKL_NUM_THREADS=1 NUMEXPR_NUM_THREADS=1
6
 
7
+ ARG BUILD_ID=10
8
+ WORKDIR /app
 
 
 
9
 
10
+ # Install dependencies
11
+ COPY requirements.txt .
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
 
14
+ # Copy app & model (make sure this filename matches your artifact)
15
+ COPY app.py best_model_random_forest.joblib ./
16
+ ENV MODEL_PATH=best_model_random_forest.joblib
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ EXPOSE 7860
 
 
 
 
 
19
 
20
+ # ✅ Use $PORT (Hugging Face default) instead of fixed 5000
21
+ CMD ["sh", "-c", "gunicorn -w 2 -k gthread --threads 2 --timeout 120 -b 0.0.0.0:$PORT app:app"]