diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..7f2de820687ee4621a7b8fd1549be0367c8d02cb
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM tiangolo/uwsgi-nginx-flask:python3.10
+
+RUN apt -qq -y update && apt -qq -y upgrade
+
+ENV STATIC_URL /static
+ENV STATIC_PATH /var/www/app/static
+COPY ./requirements_docker.txt /app/requirements.txt
+RUN python -m pip install --no-cache-dir --index-url https://support.bayesfusion.com/pysmile-A/ pysmile
+RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
+COPY . /app
+
+#EXPOSE 5000
+# Finally, we run uWSGI with the ini file we
+# created earlier
+#CMD [ "python", "./app/main.py" ]
\ No newline at end of file
diff --git a/README.md b/README.md
index 94d0b432fe79ccc277ecef2cf152604c47e26b3d..45ad17cd1cc2f8708cbaf012d99b7ca5dd2529ba 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,11 @@
 INSTALL
 python -m pip install --no-cache-dir --index-url https://support.bayesfusion.com/pysmile-A/ pysmile
 
+Docker
+https://hub.docker.com/r/tiangolo/uwsgi-nginx-flask
+
+docker compose -f docker-compose.yml up
+
 ## Getting started
 
 To make it easy for you to get started with GitLab, here's a list of recommended next steps.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5fc44b267da4d2bb5c44966f58771565f3889dc6
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,30 @@
+version: "3.9"
+services:
+  urbanite:
+    build:
+#   build: .
+      context: .
+      dockerfile: ./Dockerfile
+    container_name: urbanite-api
+    depends_on:
+      - mysqldb
+    ports:
+      - "80:80"
+    links:
+      - mysqldb:mysql
+  mysqldb:
+    image: mysql
+    restart: always
+    ports:
+      - "3308:3306"
+    environment:
+      - MYSQL_ROOT_PASSWORD=admin
+      - MYSQL_DATABASE=urbanite_recommender
+    volumes:
+      #- db-data:/var/lib/mysql
+      - ./ddbb_scripts/Dump_urbanite_recommender.sql:/docker-entrypoint-initdb.d/urbanite_recommender.sql
+
+# Names our volume
+volumes:
+  db-data:
+    driver: local
diff --git a/extra_data/Dump20230302.zip b/extra_data/Dump20230302.zip
new file mode 100644
index 0000000000000000000000000000000000000000..af81576ec78f828f9036ed2c10b8a909665b7873
Binary files /dev/null and b/extra_data/Dump20230302.zip differ
diff --git a/main.py b/main.py
new file mode 100644
index 0000000000000000000000000000000000000000..0ceb7bca5930b68d5b68694ca36832220a67669d
--- /dev/null
+++ b/main.py
@@ -0,0 +1,303 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+Created on: 16/01/2023
+@author: Andoni Aranguren Ubierna
+@updates: Sergio Campos 02-03/2023
+"""
+
+import pickle
+import pysmile
+import sys
+import json
+print(sys.path)
+from src import constants, pysmile_license
+from werkzeug.middleware.proxy_fix import ProxyFix
+
+
+import mysql.connector
+from flask import Flask, request, render_template
+
+from src import configuration, recommender, database, planner, modal_choice
+
+app = Flask(__name__)
+
+model = pickle.load(open('model.pkcls', 'rb'))
+"""
+net = pysmile.Network()
+"""
+
+#CORS
+from flask_cors import CORS
+cors = CORS(app, resources={r"/*": {"origins": "*"}})
+
+cnx = None
+
+
+@app.route("/")
+def index():
+    return render_template("index.html")
+
+
+
+# MODAL CHOICE: -------------------------------------------------------------------------------------------------------
+@app.get("/modal_choice/getConfigurationFile")
+def modal_choice_getconfigurationfile():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return modal_choice.modal_choice_getconfigurationfile(cnx, request)
+
+
+
+
+@app.get("/modal_choice/estimation")
+def modal_choice_estimation():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return modal_choice.modal_choice_estimation(cnx, request) 
+
+@app.get("/modal_choice/getProbabilites")
+def modal_choice_getprobabilities():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return modal_choice.modal_choice_getprobabilities(cnx, request)
+
+@app.get("/modal_choice/setProbabilites")
+def modal_choice_setprobabilities():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return modal_choice.modal_choice_setprobabilities(cnx, request)
+
+
+@app.get("/modal_choice/getDependencies")
+def modal_choice_getdependencies():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return modal_choice.modal_choice_getdependencies(cnx, request)
+
+
+@app.get("/modal_choice/getValues")
+def modal_choice_getvalues():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return modal_choice.modal_choice_getvalues(cnx, request)
+
+
+
+
+
+#Dexi configuration: -------------------------------------------------------------------------------------------------
+@app.get("/recommender/configuration/getMatrix")
+def configuration_getmatrix():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return configuration.getmatrix(cnx, request) 
+
+
+@app.get("/recommender/configuration/setMatrix")
+def configuration_setmatrix():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return configuration.setmatrix(cnx, request)
+
+
+@app.get("/recommender/configuration/getSliders")
+def configuration_getsliders():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return configuration.getsliders(cnx, request)
+
+
+@app.get("/recommender/configuration/setSliders")
+def configuration_setsliders():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return configuration.setsliders(cnx, request)
+
+
+
+@app.get("/recommender/configuration/getEvaluationFile")
+def configuration_getevaluationfile():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return configuration.getevaluationfile(cnx, request)
+
+
+@app.get("/recommender/configuration/getConfigurationFile")
+def configuration_getconfigurationfile():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return configuration.getconfigurationfile(cnx, request)
+
+
+
+# RECOMMENDERS: -------------------------------------------------------------------------------------------------------
+@app.get("/recommender/popularity")
+def recommender_popularity():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return recommender.recommender_popularity(cnx, request)
+
+
+@app.get("/recommender/geographic/action_id")
+def recommender_geographic_id():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return recommender.recommender_geographic_id(cnx, request)
+
+
+@app.get("/recommender/geographic/lat_lon")
+def recommender_geographic_lat_lon():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return recommender.recommender_geographic_lat_lon(cnx, request)
+
+
+@app.get("/recommender/preferences")
+def recommender_preferences():
+    """
+    We ask for kpis based on the affinity to the kpi provided.
+    :return: json
+    """
+    return recommender.recommender_preferences(cnx, request)
+
+
+@app.get("/recommender/kpis/kpi_id")
+def recommender_kpis_kpi_id():
+    """
+    Provided a action it returns a set of kpis by their affinity regarding the provided action
+    :return: json
+    """
+    return recommender.recommender_kpis_kpi_id(cnx, request)
+
+
+@app.get("/recommender/kpis/action_id")
+def recommender_kpis_action_id():
+    """
+    Provided a action it returns a set of kpis by their affinity regarding the provided action
+    :return: json
+    """
+    return recommender.recommender_kpis_action_id(cnx, request)
+
+
+@app.get("/recommender/bayesian")
+def recommender_bayesian_action_id():
+    """
+    We ask for actions based on popularity of the actions
+    :return: json
+    """
+    return recommender.recommender_bayesian_action_id(cnx, request)
+
+
+# DATABASE SAVE: -------------------------------------------------------------------------------------------------------
+@app.post("/database/save/plan")
+def database_save_plan():
+    """
+    It stores the plan_details that have been selected.
+    The json provided should have the same format that /planner/plan_detail outputs filled with each plan_detail
+    :return: json with the plan_detail
+    """
+    if request.json:
+        return database.database_save_plan(cnx, request)
+    else:
+        return constants.ERROR_JSON_NEEDED
+
+
+# plan_detail PLANNER: -------------------------------------------------------------------------------------------------------
+@app.get("/planner/plan_detail")
+def planner_plan_detail():
+    """
+    It calculates the best plan_detail traversing streets and reordering the intermediate nodes provided.
+    :return: json with the plan_detail
+    """
+    return planner.planner_plan_detail(cnx, request)
+
+@app.get("/database/store/kpi")
+def database_store_kpi():
+    """
+    The json provided should have the same format that json with the kpi
+    """
+    #if request.json:
+    if request:
+        return database.database_store_kpi(cnx, request)
+    else:
+        return constants.ERROR_JSON_NEEDED
+
+@app.get("/database/store/kpi_relative")
+def database_store_kpi_relative():
+    """
+    The json provided should have the same format that json with the kpi
+    """
+    #if request.json:
+    if request:
+        return database.database_store_kpi(cnx, request, relative=True)
+    else:
+        return constants.ERROR_JSON_NEEDED
+
+@app.get("/database/store/kpi_area")
+def database_store_kpi_area():
+    """
+    The json provided should have the same format that json with the kpi
+    """
+    #if request.json:
+    if request:
+        return database.database_store_kpi(cnx, request, area=True)
+    else:
+        return constants.ERROR_JSON_NEEDED
+
+@app.get("/database/store/kpi_relative_area")
+def database_store_kpi_relative_area():
+    """
+    The json provided should have the same format that json with the kpi
+    """
+    #if request.json:
+    if request:
+        return database.database_store_kpi_relative_area(cnx, request)
+    else:
+        return constants.ERROR_JSON_NEEDED
+
+# MAIN: ----------------------------------------------------------------------------------------------------------------
+if __name__ == "__main__":
+    """model = pickle.load(open('model.pkcls', 'rb'))
+    net = pysmile.Network()
+    net.read_file("URBANITE_ModalChoice.xdsl");
+    """
+    #cnx = mysql.connector.connect(**constants.DDBB_CONFIG)
+    user = 'root'
+    passwd = 'admin'
+    ip = 'mysql'
+    bd = 'urbanite_recommender'
+    cnx = "mysql+pymysql://%s:%s@%s/%s" % (user, passwd, ip, bd)
+    # app.run(debug=True, host='0.0.0.0')
+    # app.wsgi_app = ProxyFix( app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
+
diff --git a/requirements.txt b/requirements.txt
index b57402671669020885201b9d048e6009fd8d7104..ab567178551e4a78e0b4697e770bf1b70d36d330 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -88,7 +88,7 @@ pyzmq==25.0.0
 qasync==0.23.0
 qtconsole==5.4.1
 QtPy==2.3.0
-requests=2.28.2
+requests==2.28.2
 rfc3986==1.5.0
 scikit-learn==1.1.3
 scipy==1.10.1
diff --git a/requirements_docker.txt b/requirements_docker.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8f3169a0ba4e8c6202ae8c60d019c82a04b54853
--- /dev/null
+++ b/requirements_docker.txt
@@ -0,0 +1,7 @@
+Flask==2.2.3
+Flask-Cors==3.0.10
+mysql-connector-python~=8.0.32
+numpy==1.23.5
+Orange3==3.34.1
+requests==2.28.2
+xmltodict==0.13.0
diff --git a/uwsgi.ini b/uwsgi.ini
new file mode 100644
index 0000000000000000000000000000000000000000..7a6dcccf47f0f720a3a203aaa3fa08da3c3a273d
--- /dev/null
+++ b/uwsgi.ini
@@ -0,0 +1,4 @@
+[uwsgi]
+module = main
+callable = app
+master = true