I am creating a simple Dash app with gunicorn and nginx.
I am deploying it with docker-compose; one container for Dash Gunicorn and one container for Nginx.
My project has the following structure:
.
├── app_rwg
│ ├── src (with some sub packages)
│ ├── Dockerfile
│ ├── setup.py
│ ├── requirements.txt
│ └── run.py
├── nginx
│ ├── conf
│ └── Dockerfile
├── docker-compose.yml
However, I am getting the following errors:
rwg_app_1 | [2021-10-07 09:39:09 0000] [13] [ERROR] Exception in worker process
rwg_app_1 | Traceback (most recent call last):
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
rwg_app_1 | worker.init_process()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 134, in init_process
rwg_app_1 | self.load_wsgi()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
rwg_app_1 | self.wsgi = self.app.wsgi()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
rwg_app_1 | self.callable = self.load()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
rwg_app_1 | return self.load_wsgiapp()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
rwg_app_1 | return util.import_app(self.app_uri)
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/util.py", line 359, in import_app
rwg_app_1 | mod = importlib.import_module(module)
rwg_app_1 | File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module
rwg_app_1 | return _bootstrap._gcd_import(name[level:], package, level)
rwg_app_1 | File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
rwg_app_1 | File "<frozen importlib._bootstrap>", line 983, in _find_and_load
rwg_app_1 | File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
rwg_app_1 | File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
rwg_app_1 | File "<frozen importlib._bootstrap_external>", line 728, in exec_module
rwg_app_1 | File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
rwg_app_1 | File "/code/run.py", line 7, in <module>
rwg_app_1 | application.run_server()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/dash/dash.py", line 2033, in run_server
rwg_app_1 | self.server.run(host=host, port=port, debug=debug, **flask_run_options)
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 920, in run
rwg_app_1 | run_simple(t.cast(str, host), port, self, **options)
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/werkzeug/serving.py", line 1010, in run_simple
rwg_app_1 | inner()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/werkzeug/serving.py", line 959, in inner
rwg_app_1 | fd=fd,
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/werkzeug/serving.py", line 783, in make_server
rwg_app_1 | host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/werkzeug/serving.py", line 688, in __init__
rwg_app_1 | super().__init__(server_address, handler) # type: ignore
rwg_app_1 | File "/usr/local/lib/python3.7/socketserver.py", line 452, in __init__
rwg_app_1 | self.server_bind()
rwg_app_1 | File "/usr/local/lib/python3.7/http/server.py", line 137, in server_bind
rwg_app_1 | socketserver.TCPServer.server_bind(self)
rwg_app_1 | File "/usr/local/lib/python3.7/socketserver.py", line 466, in server_bind
rwg_app_1 | self.socket.bind(self.server_address)
rwg_app_1 | OSError: [Errno 98] Address already in use
rwg_app_1 | [2021-10-07 09:39:09 0000] [13] [INFO] Worker exiting (pid: 13)
rwg_app_1 | Traceback (most recent call last):
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 209, in run
rwg_app_1 | self.sleep()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 357, in sleep
rwg_app_1 | ready = select.select([self.PIPE[0]], [], [], 1.0)
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 242, in handle_chld
rwg_app_1 | self.reap_workers()
rwg_app_1 | File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 525, in reap_workers
rwg_app_1 | raise HaltServer(reason, self.WORKER_BOOT_ERROR)
rwg_app_1 | gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>
My run.py
:
from rwg_app.dash_app import create_app
application = create_app()
application.run_server()
My Dockerfile for Dash Gunicorn:
FROM python:3.7
RUN mkdir /code
WORKDIR /code
COPY .. .
RUN pip install -r requirements.txt
RUN pip install . --use-feature=in-tree-build
EXPOSE 8050
CMD gunicorn --bind 0.0.0.0:8050 -w 3 run:application --log-file -
My conf
for Nginx:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://rwg_app:8050;
}
}
The Dockerfile within my Nginx folder:
FROM nginx:1.19.2-alpine
COPY conf /etc/nginx/conf.d/default.conf
My final docker-compose file:
version: "3.7"
services:
rwg_app:
build: app_rwg
restart: always
ports:
- 8050:8050
networks:
- rwg_network
nginx:
build: nginx
restart: always
ports:
- 80:80
networks:
- rwg_network
depends_on:
- rwg_app
networks:
rwg_network:
I already tried:
kill -9 $(ps -A | grep python | awk '{print $1}')
But without success...
I am out of options. Please help :D
CodePudding user response:
So, before starting your Docker app, have you tried using netstat -a
to check if there is anything running on that port? See more command arguments here or just run man netstat
. Hope this will help you find what's running.
If there's nothing running on that port, you should review your configs to see whether the Docker compose up will attempt to start 2 processes on the same port (or start something twice).
CodePudding user response:
I found the answer! It's because in order to make Dash work with Gunicorn, one needs to use the Flask server and not the Dash server.
So I created another flask_app.py
and in my dash_app.py
I created the following function:
def register_dash_app(flask_app):
dash_app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP],
server=flask_app,
name='Example',
url_base_pathname="/example/")
dash_app.layout = html.Div([
html.H1('Hi there!'),
html.H4(hello_world())
]
)
return dash_app
And in flask_app.py
:
import flask
from rwg_app.dash_app import register_dash_app
from flask import Flask
app = Flask(__name__)
register_dash_app(app)
@app.route("/dashboard")
def render_dashboard():
return flask.redirect('/rwg/')
Now everything with docker-compose.