Bokeh/Flask App + gunicorn/docker + nginx/docker

Hi I’m experiencing issue on deploying a bokeh app on flask

  • gunicorn + docker + nginx (see a reference architecture below).

On a Linux Ubuntu VM running on “gczc6528tyfe” (PC name) I
have 2 docker containers.

The first docker container contains bokeh/flask app and
gunicorn. Second docker containers contains nginx. See code and configurations
below.

If I Run the application from docker compose with command “python Vibs_App_Flask.py”
(it is commented below), application successfully runs in docker container and
is reachable from any machine into local networks pointing to
“gczc6528tyfe:8000”.

However docker App it’s not reachable on location “1080/vibs” through nginx docker (note that I configured virtual machine mapping port 80 on
1080) – see also nginx configuration below. Error screenshot below.

If I Run the application from docker compose with command “command: gunicorn -w 1 -b
:8000 Vibs_App_Flask:app” (see below), applications it’s not reachable
nor from localhost, nor from local network pointing to “gczc6528tyfe:8000” or
“gczc6528tyfe:1080/vibs”.

Do you have any advice on wrong configuration that I did on bokeh side?

Thanks

Michele

======== BOKEH/FLASK APP========================================

As bokeh flask App (filename: “Vibs_App_Flask.py”) -
for simplicity, let’s use the example in GIT (https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/flask_embed.py)

From row 39 I changed code as follows as follows:

@app.route(’/’,
methods=[‘GET’])

def bkapp_page():

script = server_document(‘http://localhost:5006/vibs’)

return
render_template(“embed.html”,
script=script, template=“Flask”)

def bk_worker():

···

Can’t pass num_procs > 1 in this configuration. If you need to run multiple

processes, see e.g. flask_gunicorn_embed.py

server = Server({’/vibs’: modify_doc}, io_loop=IOLoop(),
allow_websocket_origin=[“localhost:8000”,
"gczc6528tyfe:8000”], port=8000)

server.start()

server.io_loop.start()

from threading import
Thread

Thread(target=bk_worker).start()

if name == ‘main’:

print(‘Opening single process Flask app with embedded Bokeh
application on http://localhost:8000/’)

print()

print(‘Multiple connections may block the Bokeh app in this
configuration!’)

print(‘See “flask_gunicorn_embed.py” for one way to
run multi-process’)

app.run()

==============================================================

======== DOCKER 1 SECTION: docker_compose_yml

bokeh_app:

container_name: bokeh_app

restart: always

build: ./bokeh-PoC

ports:

“8000:8000”

command: gunicorn -w 1 -b

:8000 Vibs_App_Flask:app

#command: python
Vibs_App_Flask.py

=============================================================

============ NGINX project.conf ========================

server {

listen 80;

server_name
docker_flask_gunicorn_nginx;

location /vibs {

proxy_pass http://localhost:8000;

Do not change this

proxy_set_header
Host $host;

proxy_set_header
X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

location / {

#rewrite ^/static(.*) /$1 break;

root
/static;

}

}

===================================================

======== DOCKER 2 SECTION: docker_compose_yml ========

nginx:

container_name: nginx

restart: always

build: ./nginx

ports:

“80:80”

===================================================

Hi Michele,

This is probably better asked in a Flask or nginx group since it is really not specific to Bokeh. That said, I’ve deployed flask+bokeh apps in Docker on AWS ECS behind an ELB (which is functionally similar to the nginx box in your diagram). Some things I’ve had to do in the configuration:

  1. In the flask config, set host to ‘0.0.0.0’.

class ProductionConfig(Config):

HOST = ‘0.0.0.0’

  1. In the gunicorn config, set forwarded_allow_ips to ‘*’ or to the ip address of the nginx instance if known. By default it is ‘127.0.0.1’ meaning it only trusts connections from this machine.

bind = “0.0.0.0:8080

forwarded_allow_ips = “*”

This is assuming they your flask+bokeh instance is not accessible directly from the outside world. If it is, you will want to take more secure measures.

Hope this helps.

cheers,

Dennis

···

On Fri, Aug 3, 2018 at 8:05 AM Michele Lauriola [email protected] wrote:

Hi I’m experiencing issue on deploying a bokeh app on flask

  • gunicorn + docker + nginx (see a reference architecture below).

On a Linux Ubuntu VM running on “gczc6528tyfe” (PC name) I
have 2 docker containers.

The first docker container contains bokeh/flask app and
gunicorn. Second docker containers contains nginx. See code and configurations
below.

If I Run the application from docker compose with command “python Vibs_App_Flask.py”
(it is commented below), application successfully runs in docker container and
is reachable from any machine into local networks pointing to
“gczc6528tyfe:8000”.

However docker App it’s not reachable on location “1080/vibs” through nginx docker (note that I configured virtual machine mapping port 80 on
1080) – see also nginx configuration below. Error screenshot below.

If I Run the application from docker compose with command “command: gunicorn -w 1 -b
:8000 Vibs_App_Flask:app” (see below), applications it’s not reachable
nor from localhost, nor from local network pointing to “gczc6528tyfe:8000” or
“gczc6528tyfe:1080/vibs”.

Do you have any advice on wrong configuration that I did on bokeh side?

Thanks

Michele

======== BOKEH/FLASK APP========================================

As bokeh flask App (filename: “Vibs_App_Flask.py”) -
for simplicity, let’s use the example in GIT (https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/flask_embed.py)

From row 39 I changed code as follows as follows:

@app.route(’/’,
methods=[‘GET’])

def bkapp_page():

script = server_document('[http://localhost:5006/vibs](http://localhost:5006/vibs)')
return

render_template(“embed.html”,
script=script, template=“Flask”)

def bk_worker():

#

Can’t pass num_procs > 1 in this configuration. If you need to run multiple

#

processes, see e.g. flask_gunicorn_embed.py

server = Server({'/vibs': modify_doc}, io_loop=IOLoop(),

allow_websocket_origin=[“localhost:8000”,
"gczc6528tyfe:8000”], port=8000)

server.start()
server.io_loop.start()

from threading import
Thread

Thread(target=bk_worker).start()

if name == ‘main’:

print('Opening single process Flask app with embedded Bokeh

application on http://localhost:8000/’)

print()
print('Multiple connections may block the Bokeh app in this

configuration!’)

print('See "flask_gunicorn_embed.py" for one way to

run multi-process’)

app.run()

==============================================================

======== DOCKER 1 SECTION: docker_compose_yml

bokeh_app:

container_name: bokeh_app
restart: always
build: ./bokeh-PoC
ports:
  -

“8000:8000”

command: gunicorn -w 1 -b

:8000 Vibs_App_Flask:app

#command: python

Vibs_App_Flask.py

=============================================================

============ NGINX project.conf ========================

server {

listen 80;
server_name

docker_flask_gunicorn_nginx;

location /vibs {

proxy_pass http://localhost:8000;

Do not change this

   proxy_set_header

Host $host;

    proxy_set_header

X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}
location / {

#rewrite ^/static(.*) /$1 break;

    root

/static;

}

}

===================================================

======== DOCKER 2 SECTION: docker_compose_yml ========

nginx:

container_name: nginx
restart: always
build: ./nginx
ports:
  -

“80:80”

===================================================

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/327e74b2-9c44-4cda-bf46-a55c7dec083a%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.