Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with deploy dash > 1.1 on Shinyproxy 2.3.1 #235

Closed
jfrubioz opened this issue Sep 25, 2020 · 9 comments
Closed

Issue with deploy dash > 1.1 on Shinyproxy 2.3.1 #235

jfrubioz opened this issue Sep 25, 2020 · 9 comments
Milestone

Comments

@jfrubioz
Copy link

jfrubioz commented Sep 25, 2020

Hi community,

I am trying to deploy a dash (latest build) app with Shinyproxy. It seems that the last successful dash/dash dependencies built than can work with Shinyproxy is:

dash 1.1.1
dash-bootstrap-components 0.7.1
dash-core-components 1.1.1
dash-html-components 1.0.0
dash-renderer 1.0.0
dash-table 4.1.0

I have tried a couple of fixes to launch it without luck, neither of which works with Dash > 1.1.0. I am adding the known solutions I’ve tried so far:

Method 1:
app = dash.Dash(__name__, requests_pathname_prefix='/app_direct/dash-demo/')

Method 2:

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], 
suppress_callback_exceptions=True, 
prevent_initial_callbacks=True, 
requests_pathname_prefix='/app_direct/<appname>')
#app.config.update({
#         # remove the default of '/'
#         'routes_pathname_prefix': '',
#         # remove the default of '/'
#         'requests_pathname_prefix': ''
#    })

I did try to include __name__ and/or exclude external_stylesheets
I also tried without success to move the request inside the config.update:

app.config.update({
         # remove the default of '/'
         'routes_pathname_prefix': '',
         # remove the default of '/'
         'requests_pathname_prefix': '/app_direct/<appname>/'
})

For reference, these solutions always result in none of this components loading:

polyfill@7.v1_6_0m1598451932.8.7.min.js
react@16.v1_6_0m1598451932.13.0.min.js
react-dom@16.v1_6_0m1598451932.13.0.min.js
prop-types@15.v1_6_0m1598451932.7.2.min.js
dash_bootstrap_components.v0_10_3m1598451933.min.js
bundle.v4_9_0m1598451932.js
dash_html_components.v1_0_3m1598451932.min.js
dash_core_components.v1_10_2m1598451932.min.js
dash_core_components-shared.v1_10_2m1598451932.js
dash_renderer.v1_6_0m1598451932.min.js
react-dom@16.v1_6_0m1598451932.13.0.min.js
prop-types@15.v1_6_0m1598451932.7.2.min.js
dash_bootstrap_components.v0_10_3m1598451933.min.js
bundle.v4_9_0m1598451932.js
dash_html_components.v1_0_3m1598451932.min.js
dash_core_components.v1_10_2m1598451932.min.js
dash_core_components-shared.v1_10_2m1598451932.js
dash_renderer.v1_6_0m1598451932.min.js

I would appreciate any help with this issue.

@jfrubioz
Copy link
Author

jfrubioz commented Nov 13, 2020

UPDATE: Dash 1.17.0 and ShinyProxy 2.4.1 seem to have done the trick.
Just needs:

server = flask.Flask(__name__)

app = dash.Dash(
    __name__, 
    external_stylesheets=[dbc.themes.BOOTSTRAP], 
    suppress_callback_exceptions=True,
    server = server,
    requests_pathname_prefix='/app_direct/<appname>/'
)

@LEDfan LEDfan added the question label Dec 3, 2020
@jtpoirier
Copy link

I can't reproduce this fix with Dash 1.17.0 and ShinyProxy 2.4.1. The Dash Demo works fine with older version of Dash, but it's not clear to me how the above solution should be implemented for the Dash Demo:

https://github.com/openanalytics/shinyproxy-dash-demo

Can you provide some more details?

UPDATE: Dash 1.17.0 and ShinyProxy 2.4.1 seem to have done the trick.
Just needs:

app = dash.Dash(
    __name__, 
    external_stylesheets=[dbc.themes.BOOTSTRAP], 
    suppress_callback_exceptions=True,
    server = server,
    requests_pathname_prefix='/app_direct/<appname>/'
)

@LEDfan
Copy link
Member

LEDfan commented Mar 1, 2021

Hi @jtpoirier

When creating a Dash application, you can specify some parameters. In order to make Dash work properly with ShinyProxy you''ll have to specify two parameters, with the same value. These parameters are:

  • routes_pathname_prefix
  • requests_pathname_prefix

The value of these parameters should be as follows:

/app_direct/<appname>/

You have to replace appname by the id of the app that uses Dash. To make this clear, here is a full example:
Let's say you have the following application.yml file:

proxy:
  title: Open Analytics Shiny Proxy
  logo-url: https://www.openanalytics.eu/shinyproxy/logo.png
  landing-page: /
  heartbeat-rate: 10000
  heartbeat-timeout: 60000
  port: 8080
  authentication: simple
  admin-groups: scientists
  users:
  - name: jack
    password: password
    groups: scientists
  - name: jeff
    password: password
    groups: mathematicians
  docker:
    cert-path: /home/none
    url: http://localhost:2375
    port-range-start: 20000
  specs:
   - id: dash-demo # Note: this is the id of the application
     display-name: Dash Demo Application
     port: 8050
     container-cmd: ["python", "app.py"]
     container-image: openanalytics/shinyproxy-dash-demo

Then the id of the application is dash-demo, and thus the value of the parameter becomes:

/app_direct/dash-demo/

So at the top of your dash application, you'll probably have the following python code:

app = dash.Dash(
    __name__, 
    external_stylesheets=[dbc.themes.BOOTSTRAP], 
    suppress_callback_exceptions=True,
    server = server,
    requests_pathname_prefix='/app_direct/dash-demo/',
   routes_pathname_prefix='/app_direct/dash-demo/'
)

I hope this is clear and helps. Good luck!

@LEDfan LEDfan added this to the Next milestone Mar 1, 2021
@LEDfan
Copy link
Member

LEDfan commented Mar 1, 2021

Hi @jfrubioz

We made a change that will be included in the next ShinyProxy release to make working with Dash apps easier. From that release on, every ShinyProxy app will have an environment variable SHINYPROXY_PUBLIC_PATH that basically contains the value your specified in your workaround. For the example above that thus would be /app_direct/dash-demo/.
The advantage is that you can make your Dash applications independent on the app name used in ShinyProxy.
BTW: we will also provide a way to bind this value to any environment variable, again to make apps more independent of ShinyProxy.

@jtpoirier
Copy link

Thanks for the fast responses. It sounds like your planned improvement will help.

The above code does not seem to successfully launch dash-demo with the latest version of Dash, potentially for a few reasons. "server" is not defined in the dash-demo app.py, so it won't run. If that line is removed, the app will start in the command line as below, but the container will never respond in time via the web interface. To be clear, the dash-demo works fine in this environment w/ dash ≤ 1.1.

Running on http://0.0.0.0:8050/app_direct/dash-demo/
Debugger PIN: 394-772-284
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
Running on http://0.0.0.0:8050/app_direct/dash-demo/
Debugger PIN: 807-835-959

@jfrubioz
Copy link
Author

jfrubioz commented Mar 1, 2021

@jtpoirier

Yes, I realized that I did not include any reference to the server. I updated the update to include the server = flask.Flask(__name__) line. Make sure you import flask into your module.

As @LEDfan explained, the solution relies simply on adding '/app_direct/dash-demo/' to your 'requests_pathname_prefix'. But I do not think you need to enter it into 'routes_pathname_prefix' as well. Hence, I would just make sure your python code looks like this:

app = dash.Dash(
    __name__, 
    external_stylesheets=[dbc.themes.BOOTSTRAP], 
    suppress_callback_exceptions=True,
    server = flask.Flask(__name__),
    requests_pathname_prefix='/app_direct/dash-demo/',
)

if __name__ == '__main__':
    app.run_server( 
           #make sure you have the right host address
           #host = '0.0.0.0',
    )

@jtpoirier
Copy link

Starting with the latest dash-demo release, I replaced the line 'app=dash.Dash()' with the below code as suggested. Again the server will run in command line but times out when launched from shinyproxy. I confirm that the id of the app is 'dash-demo' in my application.yml file.

import flask

app = dash.Dash(
    __name__, 
    suppress_callback_exceptions=True,
    server=flask.Flask(__name__),
    requests_pathname_prefix='/app_direct/dash-demo/'
)

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

@jtpoirier
Copy link

I see now that this solution is exclusive to >1.1 and not a general solution for all version of dash.

I've now reproduced this fix with dash-demo and a second more complex application. Thanks so much for your assistance.

@LEDfan
Copy link
Member

LEDfan commented Mar 2, 2021

Hi @jtpoirier , great that you managed to solve the issue!

@jfrubioz we released ShinyProxy 2.5.0 in which each container now has the SHINYPROXY_PUBLIC_PATH environment. As you can see in our demo it should now be easier to support newer Dash versions.
Thank you for contributing the solution to us!

Since this is fixed now, I'm closing this issue. As always, feel free to open a new issue if you encounter any problem.

@LEDfan LEDfan closed this as completed Mar 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants