# Panel server embedded in gunicorn/Flask hosted to cloud

**URL:** <https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124>\
**Category:** Panel\
**Tags:** bokeh\
**Created:** [August 21, 2020, 10:01pm UTC](https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124 "2020-08-21T22:01:46Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![\_jm](https://discourse.holoviz.org/letter_avatar_proxy/v4/letter/_/ac91a4/32.png) [@\_jm](https://discourse.holoviz.org/u/_jm)\
**Post date:** [August 21, 2020, 10:01pm UTC](https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124/1 "2020-08-21T22:01:46Z")

</div>

I have a panel server embedded in a Flask app which is run via gunicorn with multiple worker processes. This works well when served on a either a Linux or Mac OSX system on an intranet, and I verified that I can also make it available externally for quick testing purposes.

I want to take the next step to deploy it to a cloud service like Heroku or the Google App Engine, but have been unsuccessful thus far. The application builds and deploys but the panel (or bokeh model) content does not render and the JavaScript console ultimately throws a connection-timeout-error.

The panel server deployment documentation gives sufficient detail to deploy a panel server application to Heroku, but the next piece is when this needs to be run through / embedded in a web framework like Flask that is ultimately serving additional content, managing user access to certain routes, etc.

As such, the panel(bokeh) server needs to be called via `server_document()` accessors as illustrated in the “official” bokeh Github repo example here: [bokeh Flask gunicorn embed example](https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/flask_gunicorn_embed.py).

Is there an example of such an implementation being successfully deployed to Heroku?

Thanks!

---

<div class="post-metadata">

**Author:** ![philippjfr](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/philippjfr/32/7_2.png) [@philippjfr](https://discourse.holoviz.org/u/philippjfr)\
**Post date:** [August 23, 2020, 8:57pm UTC](https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124/2 "2020-08-23T20:57:22Z")

</div>

Mind filing an issue? We should add a few examples using flask with and without gunicorn to the repo.

---

<div class="post-metadata">

**Author:** ![philippjfr](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/philippjfr/32/7_2.png) [@philippjfr](https://discourse.holoviz.org/u/philippjfr)\
**Post date:** [August 23, 2020, 9:01pm UTC](https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124/3 "2020-08-23T21:01:55Z")

</div>

Note that you can always use `panel_object.server_doc(doc)` to render to a bokeh document and then use the approach outlined in the bokeh example you linked.

---

<div class="post-metadata">

**Author:** ![\_jm](https://discourse.holoviz.org/letter_avatar_proxy/v4/letter/_/ac91a4/32.png) [@\_jm](https://discourse.holoviz.org/u/_jm)\
**Post date:** [August 23, 2020, 9:57pm UTC](https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124/4 "2020-08-23T21:57:44Z")

</div>

Thanks @philippjfr

My app with Flask/gunicorn/panel works well currently. The problem I am facing is how to transition to a platform-as-a-service / cloud environment like Heroku or Google App Engine.

The code that works for me when hosting myself on a Linux or OSX computer does not work when trying on those services.

---

<div class="post-metadata">

**Author:** ![\_jm](https://discourse.holoviz.org/letter_avatar_proxy/v4/letter/_/ac91a4/32.png) [@\_jm](https://discourse.holoviz.org/u/_jm)\
**Post date:** [August 29, 2020, 12:07pm UTC](https://discourse.holoviz.org/t/panel-server-embedded-in-gunicorn-flask-hosted-to-cloud/1124/5 "2020-08-29T12:07:16Z")

</div>

Update: This works on Heroku. There is more discussion on the Bokeh Discourse site for [Topic 6199](https://discourse.bokeh.org/t/bokeh-server-embedded-in-gunicorn-flask-hosted-to-cloud/6199/13).

Here is a cut-and-paste of the main points. Some of the discussion is in the context of bokeh server, but since the panel server is the bokeh server, it all translates. In fact, the feasibility test case was using `panel serve`.

> For others that have application architectures similar that embed a **bokeh** server in a **gunicorn/Flask** framework and want to deploy it to a platform as a service / cloud service, this can be done in **Heroku** using two _dynos_ . After exhaustively exploring different mechanisms and helpful exchanges with the **Heroku** support team, getting everything to work in one _dyno_ is not possible.
> 
> **DETAILS**
> 
> _Flask-app_ which embeds the bokeh server on one _dyno_ :
> 
> Create a python Flask app, e.g. a simple one as follows, and use the Heroku Procfile to run it via **gunicorn** , which is well documented on Heroku’s site.

```auto
from flask import Flask, render_template

from bokeh.client import pull_session
from bokeh.embed import server_session

BOKEH_URL = "https://<bokeh-app-name>.herokuapp.com/<bokeh-server-name>"

app = Flask( __name__ )

@app.route('/', methods=['GET'])
def bkapp_page():
    with pull_session(url=PANEL_URL) as session:
        script = server_session(session_id=session.id, url=BOKEH_URL)
        return render_template("embed.html", script=script, template="Flask")

```

> _Bokeh server app_ which runs the bokeh server on second _dyno_ :
> 
> Implement this as usual and create a Heroku Procfile that runs the server, e.g.

`web: bokeh serve --address="0.0.0.0" --port=$PORT <bokeh-server-name> --allow-websocket-origin=<flask-app-name>.herokuapp.com`

> NB: The port argument is important b/c Heroku assigns the port that is used; you cannot choose it yourself.
> 
> NB: The quantities in \<…\> above should reflect the app names for your Heroku apps and the name of your bokeh server following the bokeh conventions if it is in single-file or directory format. Caveat, that only the single module `bokeh-server-name.py` case has been tested in determining the viability of the approach.
> 
> Thanks to @p-himik and @Bryan for the valuable help getting this to work!
