Deploy Dash on apache server [solved!]

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:

@gerrit - I just ran your example:

# -*- 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

app.layout = html.Div([])

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

Visiting http://localhost:8050 results in:

(vv) ~/Repos/dash-stuff/dash-sandbox (master)
♡♡ python dash-routes-config.py
 * Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 150-080-314
127.0.0.1 - - [12/Sep/2017 17:06:40] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [12/Sep/2017 17:06:41] "GET /pompidom3/_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [12/Sep/2017 17:06:41] "GET /pompidom3/_dash-dependencies HTTP/1.1" 200 -

With:

$ pip freeze | grep dash
dash==0.18.3
dash-core-components==0.12.5
dash-html-components==0.7.0
dash-renderer==0.9.0
dash-table-experiments==0.5.0

I copied your code, I had to make one adjustment, as I run dash on a raspberry pi without windowing system I had to put in host=‘0.0.0.0’:

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

resulting in:

pi@rpizolder ~/bin $ python testdash.py 
 * Running on http://0.0.0.0:8050/
 * Restarting with reloader
192.168.2.57 - - [13/Sep/2017 20:59:45] "GET / HTTP/1.1" 200 -
192.168.2.57 - - [13/Sep/2017 20:59:45] "GET /_dash-layout HTTP/1.1" 200 -
192.168.2.57 - - [13/Sep/2017 20:59:45] "GET /_dash-dependencies HTTP/1.1" 200 -
192.168.2.57 - - [13/Sep/2017 20:59:45] "GET /_dash-routes HTTP/1.1" 200 -

and:

$ pip freeze | grep dash
dash==0.18.3
dash-renderer==0.9.0

What is the difference with or without setting ‘routes_pathname_prefix’ to ‘/showtemperature2/’ here in this example?

Problem found, python 2.7 and 3 were mixed up.
pip freeze was referring to python3 while I was using 2.7 for running the script.

sudo easy_install-2.7 -U pip

and upgrading the components using python 2.7, made my day.

Thanks chris for your effort.

2 Likes

Thought I’d update this thread since the solutions above didn’t work for me. I think the config system changed to be constructor based somewhere along the way. I’m on dash-0.40.0 now.

The below worked for me to host my dash app off a url-prefix.

In app.py:

app = dash.Dash(__name__, external_stylesheets=external_stylesheets, routes_pathname_prefix='/blarg/')

You saved my day!!! Thanks

Those workaround doesn’t work for dash=1.14.0. Could you provide solution for this version?

3 Likes

Providing another configuration that worked for me in case people come here from Google (like me):

  • Dash app constructor with app = dash.Dash( [...] requests_pathname_prefix='/my-prefix/' [...])
  • Dash app served by waitress’ serve like serve(app.server, host='0.0.0.0', port=5000, threads=6, url_prefix='/my-prefix/')
  • Running in a docker container with -p 7005:5000
  • Apache htaccess contains RewriteRule ^my-prefix(.*) http://0.0.0.0:7005/$1 [P]
  • Access as http://my-server.com/my-prefix/
dash==2.5.0
dash-auth==1.4.1
dash-bootstrap-components==1.1.0
dash-core-components==2.0.0
dash-html-components==2.0.0
dash-table==5.0.0
1 Like