martynka commited on
Commit
37c0dcf
·
verified ·
1 Parent(s): ff13e42

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +33 -10
Dockerfile CHANGED
@@ -156,7 +156,7 @@ document.addEventListener('DOMContentLoaded', () => {
156
  });
157
  EOF
158
 
159
- # ===== Combined Server =====
160
  COPY <<"EOF" /app/combined_server.py
161
  from flask import Flask, request, jsonify, render_template, make_response
162
  from werkzeug.middleware.proxy_fix import ProxyFix
@@ -167,6 +167,8 @@ from pathlib import Path
167
  import subprocess
168
  import requests
169
  from waitress import serve
 
 
170
 
171
  app = Flask(__name__,
172
  template_folder='/app/admin/templates',
@@ -184,7 +186,7 @@ def get_db():
184
  (username TEXT PRIMARY KEY, password TEXT, role TEXT)''')
185
  return db
186
 
187
- # Admin routes
188
  @app.route('/sudo')
189
  def admin_home():
190
  return render_template('login.html')
@@ -192,7 +194,7 @@ def admin_home():
192
  @app.route('/sudo/login', methods=['POST'])
193
  def login():
194
  if request.json.get('sudo_secret') == os.getenv("SUDO_SECRET"):
195
- return jsonify({"status": "success"})
196
  return jsonify({"error": "Invalid secret"}), 403
197
 
198
  @app.route('/sudo/dashboard')
@@ -236,34 +238,55 @@ def remove_user():
236
  db.commit()
237
  return jsonify({"status": "User removed"})
238
 
239
- # LibreChat proxy
 
 
 
 
 
 
240
  @app.route('/', defaults={'path': ''})
241
- @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
242
  def proxy(path):
 
243
  if path.startswith('sudo/') or path == 'sudo':
244
  return make_response("Not Found", 404)
245
 
 
 
 
 
 
 
 
 
 
246
  resp = requests.request(
247
  method=request.method,
248
  url=f"http://localhost:3080/{path}",
249
- headers={key: value for (key, value) in request.headers if key != 'Host'},
250
  data=request.get_data(),
251
  cookies=request.cookies,
252
- allow_redirects=False
 
253
  )
254
 
 
255
  response = make_response(resp.content, resp.status_code)
256
  for key, value in resp.headers.items():
257
  if key.lower() not in ['content-encoding', 'content-length', 'transfer-encoding']:
258
  response.headers[key] = value
259
  return response
260
 
 
 
 
261
  if __name__ == "__main__":
262
- # Start LibreChat backend
263
- subprocess.Popen(["npm", "run", "backend"], cwd="/app")
264
 
265
  # Start combined server
266
- serve(app, host='0.0.0.0', port=7860, threads=4)
267
  EOF
268
 
269
  # Startup script
 
156
  });
157
  EOF
158
 
159
+ # ===== Fixed Combined Server =====
160
  COPY <<"EOF" /app/combined_server.py
161
  from flask import Flask, request, jsonify, render_template, make_response
162
  from werkzeug.middleware.proxy_fix import ProxyFix
 
167
  import subprocess
168
  import requests
169
  from waitress import serve
170
+ import threading
171
+ import time
172
 
173
  app = Flask(__name__,
174
  template_folder='/app/admin/templates',
 
186
  (username TEXT PRIMARY KEY, password TEXT, role TEXT)''')
187
  return db
188
 
189
+ # ===== Admin Routes =====
190
  @app.route('/sudo')
191
  def admin_home():
192
  return render_template('login.html')
 
194
  @app.route('/sudo/login', methods=['POST'])
195
  def login():
196
  if request.json.get('sudo_secret') == os.getenv("SUDO_SECRET"):
197
+ return jsonify({"status": "success", "token": os.getenv("SUDO_SECRET")})
198
  return jsonify({"error": "Invalid secret"}), 403
199
 
200
  @app.route('/sudo/dashboard')
 
238
  db.commit()
239
  return jsonify({"status": "User removed"})
240
 
241
+ # ===== LibreChat Proxy =====
242
+ def is_librechat_ready():
243
+ try:
244
+ return requests.get('http://localhost:3080', timeout=1).status_code < 500
245
+ except:
246
+ return False
247
+
248
  @app.route('/', defaults={'path': ''})
249
+ @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])
250
  def proxy(path):
251
+ # Don't proxy admin routes
252
  if path.startswith('sudo/') or path == 'sudo':
253
  return make_response("Not Found", 404)
254
 
255
+ # Wait for LibreChat to be ready
256
+ for _ in range(30): # 30 second timeout
257
+ if is_librechat_ready():
258
+ break
259
+ time.sleep(1)
260
+ else:
261
+ return make_response("LibreChat backend not ready", 503)
262
+
263
+ # Forward request to LibreChat
264
  resp = requests.request(
265
  method=request.method,
266
  url=f"http://localhost:3080/{path}",
267
+ headers={key: value for (key, value) in request.headers if key.lower() != 'host'},
268
  data=request.get_data(),
269
  cookies=request.cookies,
270
+ allow_redirects=False,
271
+ timeout=30
272
  )
273
 
274
+ # Create response
275
  response = make_response(resp.content, resp.status_code)
276
  for key, value in resp.headers.items():
277
  if key.lower() not in ['content-encoding', 'content-length', 'transfer-encoding']:
278
  response.headers[key] = value
279
  return response
280
 
281
+ def start_librechat():
282
+ subprocess.run(["npm", "run", "backend"], cwd="/app")
283
+
284
  if __name__ == "__main__":
285
+ # Start LibreChat in background
286
+ threading.Thread(target=start_librechat, daemon=True).start()
287
 
288
  # Start combined server
289
+ serve(app, host='0.0.0.0', port=7860, threads=4, ident="LibreChat Proxy")
290
  EOF
291
 
292
  # Startup script