Deploy Dash on apache server [solved!]

How can I run Dash from the standard apache server available (in my case) on the raspberry pi.

I followed the instructions for installing flask, which looks like about the same approach.
So I have mod_wsgi installed:

pi@rpizolder ~/bin $ cat /etc/apache2/sites-available/dash.conf 
WSGIDaemonProcess showtemperature user=pi group=pi home=/home/pi threads=5
WSGIScriptAlias /showtemperature /var/www/html/wsgi/showtemperature.wsgi
<Directory /home/pi/bin>
	WSGIProcessGroup showtemperature
        WSGIApplicationGroup %{GLOBAL}
        WSGIScriptReloading On
	Require all granted
</Directory>
pi@rpizolder ~/bin $ 

created a wsgi file:

pi@rpizolder ~/bin $ cat /var/www/html/wsgi/showtemperature.wsgi
#!/usr/bin/python
import sys
sys.path.insert(0,"/home/pi/bin/")
from showtemperature import app as application
pi@rpizolder ~/bin $ 

and took the first demo app:

    pi@rpizolder ~/bin $ cat showtemperature.py 
    # -*- coding: utf-8 -*-
    import dash
    import dash_core_components as dcc
    import dash_html_components as html

    app = dash.Dash()

    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)

    pi@rpizolder ~/bin $ 

Unfortunately when accessing the url, the server log shows an error that the .plotly folder is inaccessible, although in the configuration the proper user was defined (pi):

pi@rpizolder ~/bin $ tail -f  /var/log/apache2/error.log
[Sat Jul 08 22:18:00.158000 2017] [wsgi:error] [pid 21930] 
[Sat Jul 08 22:18:09.130181 2017] [wsgi:error] [pid 21930] [client 192.168.2.57:54791] mod_wsgi (pid=21930): Exception occurred processing WSGI script '/var/www/html/wsgi/showtemperature.wsgi'.
[Sat Jul 08 22:18:09.130685 2017] [wsgi:error] [pid 21930] [client 192.168.2.57:54791] TypeError: 'Dash' object is not callable
[Sat Jul 08 22:18:25.951932 2017] [wsgi:error] [pid 21934] /usr/local/lib/python2.7/dist-packages/plotly/tools.py:103: UserWarning:
[Sat Jul 08 22:18:25.952354 2017] [wsgi:error] [pid 21934] 
[Sat Jul 08 22:18:25.952500 2017] [wsgi:error] [pid 21934] Looks like you don't have 'read-write' permission to your 'home' ('~') directory or to our '~/.plotly' directory. That means plotly's python api can't setup local configuration files. No problem though! You'll just have to sign-in using 'plotly.plotly.sign_in()'. For help with that: 'help(plotly.plotly.sign_in)'.
[Sat Jul 08 22:18:25.952646 2017] [wsgi:error] [pid 21934] Questions? Visit https://support.plot.ly
[Sat Jul 08 22:18:25.952770 2017] [wsgi:error] [pid 21934] 
[Sat Jul 08 22:18:34.901116 2017] [wsgi:error] [pid 21934] [client 192.168.2.57:54802] mod_wsgi (pid=21934): Exception occurred processing WSGI script '/var/www/html/wsgi/showtemperature.wsgi'.
[Sat Jul 08 22:18:34.901541 2017] [wsgi:error] [pid 21934] [client 192.168.2.57:54802] TypeError: 'Dash' object is not callable

Maybe I overlook something, any help?

thanks,
Gerrit.

1 Like

Try this:

1 - Add server = app.server to the showtemperature.py file. In this case, server is the instance of the Flask server that Dash uses.
2 - Change from showtemperature import app as application to something like from showtemperature import server

thanks chriddyp, did that, and it improved a bit. but I still have the errors:

[Tue Jul 11 22:23:15.447334 2017] [wsgi:error] [pid 21282] /usr/local/lib/python2.7/dist-packages/plotly/tools.py:103: UserWarning:
[Tue Jul 11 22:23:15.447593 2017] [wsgi:error] [pid 21282] 
[Tue Jul 11 22:23:15.447645 2017] [wsgi:error] [pid 21282] Looks like you don't have 'read-write' permission to your 'home' ('~') directory or to our '~/.plotly' directory. That means plotly's python api can't setup local configuration files. No problem though! You'll just have to sign-in using 'plotly.plotly.sign_in()'. For help with that: 'help(plotly.plotly.sign_in)'.
[Tue Jul 11 22:23:15.447694 2017] [wsgi:error] [pid 21282] Questions? Visit https://support.plot.ly
[Tue Jul 11 22:23:15.447734 2017] [wsgi:error] [pid 21282] 

and my browser now shows:

Error loading layout

so looks like I had two issues from which one is solved now.

This is just a warning (“UserWarning”), you can ignore this.

There is usually some type of error in the terminal that this should correspond to. Could you open up the browser’s dev tools and take a screenshot of any red errors that might be there?

ok, it didn’t find some resources:

[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (_dash-layout, line 0)
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (_dash-dependencies, line 0)
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (_dash-routes, line 0)

Hm, not sure what’s going on here. I’ve just published a guide to heroku and gunicorn-based deployment here: https://plot.ly/dash/deployment. Not sure if it’ll help this apache case though. I’m not intimately familiar with apache myself but maybe somebody else in the community is.

Not sure if you fixed this already, but trying something like this may help (fixed the issue on my side, trying to serve Dash apps in Apache):

from showtemperature import server as application

1 Like

thanks, bit I’m still struggling with this, that is to say, today I tried again, but unfortunately without success.
The problem is that the server can not find:
/_dash-layout
/_dash-dependencies
/_dash-routes

When running from the built in server, on the command line I see these pages are loaded with http GET. When running on apache there is a 404 (not found) error.

I indeed have

from showtemperature import server as application

in my wsgi file.

The complete configuration is as follows:

pi@rpizolder ~/bin $ cat /var/www/html/wsgi/showtemperature.wsgi 
#!/usr/bin/python
import sys
sys.path.insert(0,"/home/pi/bin/")
from showtemperature import server as application

and:

pi@rpizolder ~/bin $ cat /etc/apache2/sites-enabled/dash.conf 
	WSGIDaemonProcess showtemperature user=pi group=pi home=/home/pi threads=5
	WSGIScriptAlias /showtemperature /var/www/html/wsgi/showtemperature.wsgi
	<Directory /home/pi/bin>
		WSGIProcessGroup showtemperature
       		WSGIApplicationGroup %{GLOBAL}
       		WSGIScriptReloading On
		Require all granted
	</Directory>
pi@rpizolder ~/bin $

I am facing a very similar issue; this is my config:

# cat test.wsgi
import sys

#Expand Python classes path with your app's path
sys.path.insert(0, "/xyz/apache/www/html/dash/")

from app import server
 application = server

and

# cat app.py
# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()
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'
            }
        }
    )
])
server = app.server

if __name__ == '__main__':
    app.run_server(debug=True)

and

[Mon Aug 28 18:01:27 2017] [error] [client 10.3.7.168] File does not exist: /xyz/apache/www/html/_dash-layout, referer: http://web/dash/
[Mon Aug 28 18:01:27 2017] [error] [client 10.3.7.168] File does not exist: /xyz/apache/www/html/_dash-dependencies, referer: http://web/dash/

The error that I see is ‘Error loading layout’

thats exactly the same problem, good to know that not on my own.

Just to add my webserver is configured behind a proxy, not sure if that has something to do with this error. I also tried changing the os.environ variable in the app.py file but that also results in the same error. It would be great if someone can help with this.

Also, want to point out the below error is trying to load _dash-layout & _dash-dependencies from the primary www/html/ directory while the app is present in www/html/dash/ folder if that points to a specific problem:

[Mon Aug 28 18:01:27 2017] [error] [client 10.3.7.168] File does not exist: /xyz/apache/www/html/_dash-layout, referer: http://web/dash/
[Mon Aug 28 18:01:27 2017] [error] [client 10.3.7.168] File does not exist: /xyz/apache/www/html/_dash-dependencies, referer: http://web/dash/

I have the same problem.

My app tries to load /_dash-component-suites/dash_core_components/rc-slider@6.1.2.css?v=0.12.4.
However, the proper path is /myapp/_dash-component-suites/dash_core_components/rc-slider@6.1.2.css?v=0.12.4.

How can I adjust?
I changed url_base_pathname and app.config.requests_pathname_prefix, but it doesn’t work.

1 Like

Try change the dash.conf to
WSGIScriptAlias / /var/www/html/wsgi/showtemperature.wsgi
You can set then the relative path of your app in dash code as:
app = dash.Dash(name=‘your_app_name’,sharing=True, server=server.server, url_base_pathname=’/showtemperature’)

If your app is multi routed, check here https://github.com/plotly/dash/pull/70

If the WSGI alias is set to non-root, e.g.
WSGIScriptAlias /path_to_dash_app /var/www/html/wsgi/showtemperature.wsgi
But inside dash, it’s not ware of that alias path. It will still trying to load components say dash-layout from the root path plus url_base_pathname.

@chriddyp is it the case?

My problem has been solved. (Deploy Dash on apache server [solved!])

*.conf is the following.

ProxyPass /myapp/ http://localhost:8050/myapp/
ProxyPassReverse /myapp/ http://localhost:8050/myapp/

And I set url_base_pathname to /myapp/.

That only works when only the python program is served by apache.

Even

is not needed in that case.

In my case /showtemperature is one of the many pages I like to serve.

If I understand well, apache is just a gateway to the internal Dash server in this case.

Having the same problems. I tried to fix them by redirecting the requests to /_dash-layout and /_dash-dependencies to the correct path. After this the layout loads correctly but the graphs don’t work since the POST to /_dash-update-component goes to the wrong path which can’t be fixed with a redirect. There should be a configurable variable to set the path for the directory in the case that the Dash app isn’t hosted in the root url of the server.

This should be the url_base_pathname. Additionally, I have added two additional config properties:

  • routes_pathname_prefix - This adds a prefix to the name of the backend routes that the server expects. This is initialized to url_base_pathname
  • requests_pathname_prefix - This adds a prefix to the API calls that are made by the Dash front-end to the server. This is initialized to url_base_pathname

So, if your app is served under /my-proxy/ but your proxy server removes the /my-proxy/ prefix before forwarding the request to the underlying dash server, you can set

app.config.update({
    # as the proxy server will remove the prefix
    'routes_pathname_prefix': '/', 

    # the front-end will prefix this string to the requests
    # that are made to the proxy server
    'requests_pathname_prefix': '/my-proxy/'
})

However, if your proxy server does not remove this prefix before forwarding the requests, you can just set both of these variables to the same prefix.

These variables are new, so you’ll need to upgrade to the latest dash and dash-renderer:

pip install dash==0.18.3
pip install dash-renderer==0.9.0
2 Likes

Tested the new prefixes and now it works! Thanks for the quick reply & fix.

1 Like

unfortunately not in my case.

code:

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import csv
from datetime import datetime as dt

app = dash.Dash(__name__)
app.config.update({
    #'url_base_pathname': '/showtemperature1/',
    # as the proxy server will remove the prefix
    'routes_pathname_prefix': '/showtemperature2/', 

    # the front-end will prefix this string to the requests
    # that are made to the proxy server
    'requests_pathname_prefix': '/pompidom3/'
})
server = app.server

print app.config

output:

pi@rpizolder ~/bin $ python showtemperature.py 
{'requests_pathname_prefix': '/pompidom3/', 'suppress_callback_exceptions': False, 'routes_pathname_prefix': '/showtemperature2/'}
 * Running on http://0.0.0.0:8050/
 * Restarting with reloader
{'requests_pathname_prefix': '/pompidom3/', 'suppress_callback_exceptions': False, 'routes_pathname_prefix': '/showtemperature2/'}
192.168.2.57 - - [12/Sep/2017 22:13:25] "GET / HTTP/1.1" 200 -
192.168.2.57 - - [12/Sep/2017 22:13:26] "GET /_dash-layout HTTP/1.1" 200 -
192.168.2.57 - - [12/Sep/2017 22:13:26] "GET /_dash-dependencies HTTP/1.1" 200 -
192.168.2.57 - - [12/Sep/2017 22:13:26] "GET /_dash-routes HTTP/1.1" 200 -

where I expected “GET /pompidom3/_dash-routes HTTP/1.1” 200 -
etc.

:confused: