✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

Hosting multiple Dash apps with uWSGI + Nginx

I am currently trying to host multiple apps using uWSGI and Nginx. When I just host this on the server without trying to mount it, the Dash app works fine, and I’ve been using it for a while now. However, it’s when I try to host multiple apps that things start going awry. I am mounting these on myurl/apps/, so I’ll have myurl/apps/app1, myurl/apps/app2, and so on. When I just create a basic Flask app as a dummy app, this works fine. However, for the Dash app, I get “Error loading layout”. In the Nginx error log I have:

2017/11/11 21:54:38 [error] 23768#23768: *3373 open() "/var/www/html/_dash-dependencies" failed (2: No such file or directory), client: <redacted>, server: <redacted>, request: "GET /_dash-dependencies HTTP/1.1", host: "<redacted>", referrer: "myurl/apps/app1/"

and a similar thing for _dash-layout.

I have an Nginx config file which looks like this:

server {
    listen 80;
    server_name <redacted ip> <redacted url>;
    root /var/www/html;

    location /apps/app1/ {
        include uwsgi_params;
        uwsgi_pass unix:/var/tmp/app1.sock;
        uwsgi_param SCRIPT_NAME /apps/app1/;
    }

    location /apps/app2/ {
        include uwsgi_params;
        uwsgi_pass unix:/var/tmp/app2.sock;
        uwsgi_param SCRIPT_NAME /apps/app2/;
    }

# and then a bunch of SSL stuff here...
}

app1 here is my Dash app and app2 is the Flask app. As noted, the Flask app runs fine, but the Dash app returns the aforementioned errors.

My app1.ini file looks like this:

[uwsgi]

base=/var/www/%n
chdir = /home/ubuntu/%n       
module = wsgi:application

master = true
processes = 5

uid=ubuntu
gid=www-data

virtualenv=/home/ubuntu/%n/venv

socket = /var/tmp/%n.sock
chmod-socket = 666
vacuum = true

mount = /apps/%n=wsgi:application

manage-script-name = true

die-on-term = true

I use the same thing for all apps. Any idea what’s going on here? I assume it has something to do with Nginx looking in the wrong place for _dash-layout, etc., but I’m not sure why. Supposedly, adding “uwsgi_param SCRIPT_NAME /apps/app2/;” to the Nginx config file should take care of that (I’ve also tried adding “uwsgi_modifier1 30;” which doesn’t resolve the issue). Just to reiterate, my Dash app works fine when I just run it on the server without trying to do any of this mounting business, so it’s presumably something to do with it looking in the wrong place for the layout. I’ve googled this pretty exhaustively and I’m running out of things to try so thought I’d ask the community for help.

Edits: Clarification.

I’m guessing that the problem is that the automatically generated routes for the two dash apps are conflicting with each other. I would expect this to not work if you just tried to run two Dash apps alongside each other. For example both apps would be trying to use /_dash-dependencies.

Setting the url_base_pathname parameter for to something distinct for each app is what you want to do. eg

app1 = Dash(__name__, url_base_pathname='/app1') 

The other thing I’ve seen suggested is to create a Flask instance that routes requests to the Flask instances of the two different apps. Something like this, although I haven’t actually tried it. It’s likely the routes might need some tweaking. The default value for url_base_pathname is ‘/’ so that definitely needs modifying here.

from dash import Dash
from flask import Flask 
from werkzeug.wsgi import DispatcherMiddleware

app1 = Dash(url_base_pathname='')
app2 = Dash(url_base_pathname='')
flask_app = Flask()

app = DispatcherMiddleware(flask_app, {
    '/app1': dash_app1.server,
    '/app2': dash_app2.server,
})
1 Like

Cheers for the reply. So changing the url base pathname didn’t improve matters. And this happens whether I use one or two Dash apps. Note that in the above example, I used a Flask app as my second app and that works. So I’m running a single Dash app and it returns the aforementioned error. Actually, is there a reference somewhere on what /_dash_dependencies and /_dash_layout is? Are these directories which contain stuff that Dash needs or what’s the deal with those? I’m sort of hoping that if I understand it a bit better, I might be able to hack my way to a solution.

I had a similar error regarding the ‘Error loading layout’ with 404s occuring for _dash-dependencies and _dash-layout. I’m using a slightly different setup. But this was the code that fixed it for me.

# In order to work on shinyproxy (and perhaps other middleware)
app.config.supress_callback_exceptions = True  
app.config.update({  
    # remove the default of '/'
    'routes_pathname_prefix': '',

    # remove the default of '/'
    'requests_pathname_prefix': ''
})

I posted a blog about this yesterday, it might help you.

3 Likes

Sorry, only got around to looking at this now. That actually solved my problem, thanks a million! Strange little thing.

1 Like

For the sake of completeness I just wanted to add to the answers above, that hosting an app app1 under myserver/app1 (without the trailing /) requires an app-config as follows:

app.config.update({
    'routes_pathname_prefix': 'app1/',

    'requests_pathname_prefix': 'app1/'
})

In the nginx conf you can add automatic forwarding using a simple rewrite.

2 Likes

Hi,
Sorry for reviving this topic, but it looks like the author @geebr passed a SOCKET to the UWSGI and NGINX. Can Dash provide a socket?