Bokeh and Flask on Heroku

Hi everyone,

first, thanks for this great project and helpful community!

I’m
working on a small flask app which renders a few templates and embeds interactive bokeh plots with widgets from bokeh serve plot (which is why
I can’t use components, which so far only give me plots without widget responses). I can get the template to render both locally and on Heroku,
however on Heroku the plots (scripts from autoload_server()) are not displaying, and no error is generated anywhere.

This is where I suspect the root of the problem, although I’m mentally stuck in solving it:
When
running locally, debugging with firebug etc. shows that the page source
looks like desired according to the template, with the {{ script | safe
}} embed looking like this:

<script
    src="http://127.0.0.1:5006/plot/autoload.js?bokeh-autoload-element=d2af1a37-1349-4b12-a15e-23610fe1d7f8"
    id="d2af1a37-1349-4b12-a15e-23610fe1d7f8"
    data-bokeh-model-id=""
    data-bokeh-doc-id=""
></script>

``

which when inspecting the html shows a generated “div class=‘bk-root’ " followed by two links to bokeh and bokeh widget min.css - which is the expected behaviour, I guess.
The same source code on Heroku then does not generate the “div class=‘bk-root’ " etc, but rather simply gets embedded into the page in its raw text form.
I think that for some reason there is some missing link between script and “div”, where the browser looks at the src=”” attrib and then on the users local machine for the bokeh server and not in the VM on heroku.

This is what I do:
The relevant part in the app currently looks like this:
@app.route("/plot")
def plot():
script = autoload_server(model=None, app_path="/plot", url=“http://127.0.0.1:5006”)
return render_template(
“plot.html”,
script = script
)

``

and the template:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
   
  <title>Plot Title</title>
  <link
      href="https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.css"
      rel="stylesheet" type="text/css">
  <link
      href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.css"
      rel="stylesheet" type="text/css">

  <script src="https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.js"></script>
  <script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.js"></script>

    <link rel=stylesheet type=text/css href="static/css/style.css">
  </head>
    <div class=page>
      <body>
      some text and h and p tags
      {{ script | safe }}
      </body>
  </div>
</html>

``

I start both processes with a Procfile looking like that:
web: gunicorn app:app
bokeh: bokeh serve plot.py --port=5006 --host=127.0.0.1:5006 --address=127.0.0.1 --allow-websocket-origin=127.0.0.1:5006 --allow-websocket-origin=0.0.0.0:5000 --host=localhost:5006

``

Both processes run on the same dyno (virtual machine) and according to Heroku support are able to communicate - but only the web app process is allowed to communicate with the outside world, any interprocess communication would have to happen within the VM (dyno):

You should be able to bind to localhost, does using 127.0.0.1
as the binding IP and also the request address work? Alternatively might you be able to try a UNIX socket? That is quite common for IPC on-dyno. Depending on the clients and servers used it’s often just a matter of updating the listen URL and request URL.

So i think my question would be: How do I tell flask to connect to the bokeh server and to generate the div directly (still providing widget interactivity and reading data from the server), instead of relaying the unconverted script tag to the end browser?

I hope I provided all relevant information, if not I’ll try to provide it as requested.
Thanks for your help!

Christopher

I did not solve the original problem, but my current workaround indeed was to split up the processes into two dynos, one running the bokeh server and one running the flask app. The bokeh server has been configured to accept outside connections, the flask app loads the plots with autoload_server() as previously, but pointing to the bokehservername.herokuapp.com url.

Hi Christopher,

Would you mind showing me how you did that? I am currently having the same problem and would really appreciate your help here. I have been looking for the solution for days.

Best,

Kean

···

On Thursday, November 17, 2016 at 2:32:29 AM UTC+11, Christopher Kittel wrote:

I did not solve the original problem, but my current workaround indeed was to split up the processes into two dynos, one running the bokeh server and one running the flask app. The bokeh server has been configured to accept outside connections, the flask app loads the plots with autoload_server() as previously, but pointing to the bokehservername.herokuapp.com url.