|
|
| Line 1: |
Line 1: |
| − | ==Deploying a Dash App==
| + | ~ Migrated |
| − | https://dash.plot.ly/deployment
| |
| − | | |
| − | | |
| − | Dash uses Flask under the hood. This makes deployment easy: you can deploy a Dash app just like you would deploy a Flask app. Almost every cloud server provider has a guide for deploying Flask apps. There is also a Dash Deployment Server, but is not free (commercial).
| |
| − | | |
| − | * Flask Deployment
| |
| − | * Dash Deployment Server (commercial)
| |
| − | | |
| − | | |
| − | <br />
| |
| − | ===Flask Deployment===
| |
| − | https://flask.palletsprojects.com/en/1.1.x/deploying/
| |
| − | | |
| − | <span style="color:#0000FF; background:#F0E68C">'''Es este archivo está paso por paso el procedimiento que realicé la última vez to deploy my Dash Application en AWS: '''</span> [[File:Deploying_a_Dash_App_in_AWS.zip]]
| |
| − | | |
| − | | |
| − | * '''Deploying a Gunicorn server''' - This is the official page. It doesn't explain well how to do it: http://docs.gunicorn.org/en/latest/deploy.html
| |
| − | | |
| − | | |
| − | * This tutorial explain well how to do deploy a Flask Applications with <code>Gunicorn</code> and <code>Nginx</code>: https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-16-04
| |
| − | | |
| − | | |
| − | * Now, when using <code>Dash</code>, we have to make a few changes with respect to the above tutorial. The following posts helped me to find the solution:
| |
| − | : https://community.plot.ly/t/error-with-gunicorn/8247
| |
| − | : https://community.plot.ly/t/failed-to-find-application-object-server-in-app/13723
| |
| − | | |
| − | | |
| − | <br />
| |
| − | '''Deploying a Dash aplications with Gunicorn and Nginx on Ubuntu 16.04''' (based on https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-16-04)
| |
| − | | |
| − | | |
| − | * '''Create and activate a Python Virtual Environment :'''
| |
| − | : <span style="color:red">See this source to understand how to create a virtualenv for an specific python version</span>: https://help.dreamhost.com/hc/en-us/articles/115000695551-Installing-and-using-virtualenv-with-Python-3
| |
| − | | |
| − | ::<syntaxhighlight lang="bash">
| |
| − | sudo pip3 install virtualenv
| |
| − | | |
| − | mkdir ~/myproject
| |
| − | cd ~/myproject
| |
| − | | |
| − | virtualenv myprojectenv # This will install a local copy of Python and pip into a directory called myprojectenv
| |
| − | | |
| − | source myprojectenv/bin/activate
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | :: Your prompt will change to indicate that you are now operating within the virtual environment. It will look something like this:
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | (myprojectenv)user@host:~/myproject$.
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | | |
| − | * '''Install Flask, Dash and Gunicorn inside the virtual environment:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | pip install gunicorn flask
| |
| − | | |
| − | ver «Dash» installation
| |
| − | ver «gunicorn» installation
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | | |
| − | * '''Create a Sample App:'''
| |
| − | :: <syntaxhighlight lang="python">
| |
| − | import os
| |
| − | import dash
| |
| − | import dash_core_components as dcc
| |
| − | import dash_html_components as html
| |
| − | | |
| − | external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
| |
| − | | |
| − | app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
| |
| − | | |
| − | server = app.server
| |
| − | | |
| − | app.layout = html.Div(children=[
| |
| − | html.H1(children='Hello Dash'),
| |
| − | | |
| − | html.Div(children='''
| |
| − | Dash: A web application framework for Python.
| |
| − | '''),
| |
| − | | |
| − | dcc.Graph(
| |
| − | id='example-graph',
| |
| − | figure={
| |
| − | 'data': [
| |
| − | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
| |
| − | {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
| |
| − | ],
| |
| − | 'layout': {
| |
| − | 'title': 'Dash Data Visualization'
| |
| − | }
| |
| − | }
| |
| − | )
| |
| − | ])
| |
| − | | |
| − | if __name__ == '__main__':
| |
| − | app.run_server(debug=True, host='0.0.0.0')
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | :: <span style="color:#FF0000">Notice that we have included: <code>server = app.server</code>.</span>
| |
| − | | |
| − | | |
| − | | |
| − | * '''Now, you can test your Dash app by typing:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | (myprojectenv)$ python myproject.py
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | :: Visit your server's domain name or IP address followed by :<code>port</code> in your web browser to verify your App is working.
| |
| − | | |
| − | | |
| − | | |
| − | * '''Create the WSGI Entry Point:''' We'll create a file that will serve as the entry point for our application. This will tell our Gunicorn server how to interact with the application:
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | (myprojectenv)$ vi ~/myproject/wsgi.py
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | :: <syntaxhighlight lang="python">
| |
| − | from myproject import server
| |
| − | | |
| − | if __name__ == "__main__":
| |
| − | server.run()
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | :: <span style="color:#FF0000">Notice that we have import the variable <code>server</code> from <code>myproject.py</code></span>
| |
| − | :: <span style="color:#FF0000">This is the different with respect to a pure Flask application, where you would import <code>App</code> instead of <code>server</code>. In Dash, we require <code>app.server</code>, which is in the <code>server</code> variable we have created. So if we were deploying a pure flak App, it would be:</span>
| |
| − | ::: <syntaxhighlight lang="shell">
| |
| − | from myproject import app
| |
| − | | |
| − | if __name__ == "__main__":
| |
| − | app.run()
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | | |
| − | * '''Testing Gunicorn's Ability to Serve the Project:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | (myprojectenv)$ cd ~/myproject
| |
| − | (myprojectenv)$ gunicorn --bind 0.0.0.0:5000 wsgi:server
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | :: <span style="color:#FF0000">For a pure Flask application, would be <code>wsgi:App</code>.</span>
| |
| − | | |
| − | :: Visit your server's domain name or IP address with :<code>port</code> appended to the end in your web browser again.
| |
| − | | |
| − | | |
| − | * '''We're now done with our virtual environment, so we can deactivate it:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | (myprojectenv)$ deactivate
| |
| − | </syntaxhighlight>
| |
| − | :: Any Python commands will now use the system’s Python environment again.
| |
| − | | |
| − | | |
| − | | |
| − | * '''Create a <code>systemd Unit</code> File:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | $ vi /etc/systemd/system/myproject.service
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | :: <syntaxhighlight lang="bash">
| |
| − | [Unit]
| |
| − | Description=Gunicorn instance to serve myproject
| |
| − | After=network.target
| |
| − | | |
| − | [Service]
| |
| − | User=root
| |
| − | Group=www-data
| |
| − | WorkingDirectory=/root/myproject
| |
| − | Environment="PATH=/root/myproject/myprojectenv/bin"
| |
| − | ExecStart=/root/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:server
| |
| − | | |
| − | [Install]
| |
| − | WantedBy=multi-user.target
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | | |
| − | * '''We can now start the Gunicorn service we created and enable it so that it starts at boot:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | $ sudo systemctl start myproject
| |
| − | $ sudo systemctl enable myproject
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | | |
| − | * '''Configuring Nginx to Proxy Requests:'''
| |
| − | :: <syntaxhighlight lang="shell">
| |
| − | $ vi /etc/nginx/sites-available/default
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | | |
| − | :: <syntaxhighlight lang="bash">
| |
| − | # Esta es la configuración por defecto (eliminando lo que en el archive original está comentado para simplificarlo aquí)
| |
| − | server {
| |
| − | listen 80 default_server;
| |
| − | listen [::]:80 default_server;
| |
| − | | |
| − | index index.html index.htm index.nginx-debian.html;
| |
| − | | |
| − | server_name _;
| |
| − | | |
| − | location / {
| |
| − | include proxy_params;
| |
| − | proxy_pass http://unix:/home/ubuntu/SADashboard/index.sock;
| |
| − | }
| |
| − | | |
| − | }
| |
| − | | |
| − | | |
| − | # Aquí estamos realizando la configuración
| |
| − | server {
| |
| − | listen 80;
| |
| − | server_name awsdashboard.sinfronteras.ws;
| |
| − | | |
| − | location / {
| |
| − | include proxy_params;
| |
| − | proxy_pass http://unix:/home/ubuntu/SADashboard/index.sock;
| |
| − | }
| |
| − | }
| |
| − | </syntaxhighlight>
| |
| − | :: <span style="color:#FF0000">ES EXTREMADAMENTE IMPORTANTE NOTAR QUE «gofaaaz.sinfronteras.ws» no puede ser reemplazado por la IP del server. La última vez perdí muchísimo tiempo porque intenté hacerlo con la IP y no funcionaba; pues la IP va hacial el «default_server;» y buscá el directorio root de nginx. Tampoco funciona si no se hace esta modificación en Nginx y se trata de acceder sólo con la IP:PORT en donde hemos iniciado la Dash applicatioin. Lo que tuve que hacer para que funcionara fue crear un subdominio y agregar el subdominio en vez de la IP como se muestra a continuación. </span>
| |
| − | | |
| − | | |
| − | :: <span style="color:#FF0000">Ahora, si queremos ingresar a la aplicación Dash utilizando al IP del server, podemo realizar la configuración de la siguiente forma. Note que en «location» hemos configurado la ruta hacia el «index.sock» en donde está corriendo la Dash Application</span>
| |
| − | :: <syntaxhighlight lang="bash">
| |
| − | server {
| |
| − | listen 80 default_server;
| |
| − | listen [::]:80 default_server;
| |
| − | | |
| − | index index.html index.htm index.nginx-debian.html;
| |
| − | | |
| − | server_name _;
| |
| − | | |
| − | location / {
| |
| − | include proxy_params;
| |
| − | proxy_pass http://unix:/home/ubuntu/SADashboard/index.sock;
| |
| − | }
| |
| − | | |
| − | }
| |
| − | | |
| − | | |
| − | # server {
| |
| − | # listen 80;
| |
| − | # server_name awsdashboard.sinfronteras.ws;
| |
| − | #
| |
| − | # location / {
| |
| − | # include proxy_params;
| |
| − | # proxy_pass http://unix:/home/ubuntu/SADashboard/index.sock;
| |
| − | # }
| |
| − | # }
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | | |
| − | * '''Finally, we restart the Nginx process:'''
| |
| − | :: <syntaxhighlight lang="bash">
| |
| − | sudo systemctl restart nginx.service
| |
| − | </syntaxhighlight>
| |
| − | :: You should now be able to go to your server's domain name or IP address in your web browser and see your App.
| |
| − | | |
| − | | |
| − | <br />
| |