Finalize production docker build
shankari opened this issue · 16 comments
I am not sure if the production docker build was ever finalized.
I see a comment from @AlirezaRa94
#21 (comment)
indicating that
I haven't yet tested the production docker-compose, and it is not ready for your testing. I will let you know when it's done.
I haven't seen a comment indicating that it is actually complete, and I see several issues in the startup logs below.
- loading test data on startup!!! ❗ ❗ 😱
- push service is not configured
- using a development server not suitable for production
DB host = ...
Connecting to database URL ...
emission/tests/data/real_examples/shankari_2015-07-22
Loading file emission/tests/data/real_examples/shankari_2015-07-22
After registration, test_july_22 -> cd78a80c-45f1-49be-8985-7ad685902bb3
Finished loading 0 entries into the usercache and 1906 entries into the timeseries
WARNING:root:push service not configured, push notifications not supported
INFO:dash.dash:Dash is running on http://0.0.0.0:.../admin/
Connecting to database URL ...
Dash is running on http://0.0.0.0:.../admin/
* Serving Flask app 'app_sidebar_collapsible'
* Debug mode: off
INFO:werkzeug:�[31m�[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.�[0m
I tested the production docker-compose, and it worked without any problems. It is ready to use with an appropriate production server. However, some modifications to the Dockerfile or other files may be necessary before deploying it in a production environment.
@AlirezaRa94 it is not ready to work on production yet. As a concrete example, even the production docker-compose
loads test data into the database on startup. This is not acceptable - it will pollute the real database and mess up the results
Please see the list of issues I've identified just by looking at the startup logs
#32 (comment)
- loading test data on startup!!! ❗ ❗ 😱
- push service is not configured
- using a development server not suitable for production
@AlirezaRa94 is there an ETA for fixing this? As I said via email, I would like to push the phone app to production this weekend, and I was hoping to push the admin dashboard to production at the same time as well as parallel features.
@AlirezaRa94 it is not ready to work on production yet. As a concrete example, even the production
docker-compose
loads test data into the database on startup. This is not acceptable - it will pollute the real database and mess up the resultsPlease see the list of issues I've identified just by looking at the startup logs #32 (comment)
- loading test data on startup!!! ❗ ❗ 😱
- push service is not configured
- using a development server not suitable for production
As I mentioned here #32 (comment), it needs some modifications to other files.
@AlirezaRa94 is there an ETA for fixing this? As I said via email, I would like to push the phone app to production this weekend, and I was hoping to push the admin dashboard to production at the same time as well as parallel features.
The problem of loading test data has been solved.
The problem of loading test data has been solved.
Great! What about the "development server not suitable for production"?
The problem of loading test data has been solved.
Great! What about the "development server not suitable for production"?
As I know, you can use Gunicorn or uWSGI in your production environment.
As I know, you can use Gunicorn or uWSGI in your production environment.
Can you change the production docker-compose to support that? In general, it would be good to have the production docker file work "out of the box", only requiring API key/config file changes to work.
push service is not configured
I am fine with holding off on this one since it is a config, although we should probably document how to configure it.
@AlirezaRa94 Do you have an ETA for when the final production blocker will be done?
blocker
I will be on leave starting tomorrow for one month and won't be available during that time. I will be able to work on it once I return.
@AlirezaRa94 so you suggest that we wait for a month to deploy this to production?!
I really don't see how that is acceptable
I made a last minute, late night change in an hour to unblock the time use survey, and am disappointed that the admin dashboard will continue to be blocked for another whole month.
wrt
As I know, you can use Gunicorn or uWSGI in your production environment.
I tried using this with gunicorn
gunicorn app_sidebar_collapsible:server -b :8050
It fails with
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
worker.init_process()
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/workers/base.py", line 134, in init_process
self.load_wsgi()
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
self.wsgi = self.app.wsgi()
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
return self.load_wsgiapp()
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
return util.import_app(self.app_uri)
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/gunicorn/util.py", line 359, in import_app
mod = importlib.import_module(module)
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/usr/src/app/app_sidebar_collapsible.py", line 40, in <module>
app = Dash(
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/dash/dash.py", line 400, in __init__
pages_folder=pages_folder_config(name, pages_folder, use_pages),
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/dash/_configs.py", line 136, in pages_folder_config
raise exceptions.InvalidConfig(error_msg)
dash.exceptions.InvalidConfig: A folder called `pages` does not exist. If a folder for pages is not
required in your application, set `pages_folder=""`. For example:
`app = Dash(__name__, pages_folder="")`
There is clearly a pages folder
app_sidebar_collapsible.py
pages
It's not clear what the working directory for gunicorn
is
I am also not sure that we need to fix this ASAP. We already run this behind an ngnix proxy, and we assume that most other deployers will do so as well to get the microservices to work together.
Will spend a little bit of time trying to get this to work but will punt on this for now otherwise
Looking at the initial commit, we had a file called Procfile
67f6c5b#diff-0a99231995da379e7aebabe76c9d849a23737a42c3b3a8994043e2aa80958424
with the contents
web: gunicorn app:server
Procfiles are used in heroku and similar web hosting platforms.
So gunicorn app:server
should work
But note that, while comparing app.py
and app_sidebar_collapsible.py
, the new app uses pages and the old one does not
Per https://stackoverflow.com/a/44664876/4040267
we should use chdir
to specify the working directory for gunicorn
Let's see if that works...
Did not work. Same error
File "/usr/src/app/app_sidebar_collapsible.py", line 40, in <module>
app = Dash(
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/dash/dash.py", line 400, in __init__
pages_folder=pages_folder_config(name, pages_folder, use_pages),
File "/root/miniconda-23.1.0/envs/emission/lib/python3.9/site-packages/dash/_configs.py", line 136, in pages_folder_config
raise exceptions.InvalidConfig(error_msg)
dash.exceptions.InvalidConfig: A folder called `pages` does not exist. If a folder for pages is not
required in your application, set `pages_folder=""`. For example:
`app = Dash(__name__, pages_folder="")`
This has a clue:
https://stackoverflow.com/questions/73906943/dash-app-cannot-find-pages-folder-when-deploying-on-gcp-using-gunicorn
But I'm not using DashProxy
. This is taking too long and getting too complicated and I will punt on it for now given that it is running behind an ngnix reverse proxy anyway
For the record, the code to wrap the code in gunicorn should look something like this
diff --git a/docker/start.sh b/docker/start.sh
index 05b2f12..b961778 100755
--- a/docker/start.sh
+++ b/docker/start.sh
@@ -12,4 +12,13 @@ fi
# run the app
# python app.py
-python app_sidebar_collapsible.py
+if [[ $DASH_DEBUG_MODE == "True" ]]; then
+ echo "Debug mode set, running flask directly"
+ python app_sidebar_collapsible.py
+else
+ echo "Debug mode not set, running using gunicorn"
+ echo "We support only 3 admin users at a time, and they are unlikely to all be logged in at the same time"
+ echo "So let's stick to the default single worker thread to avoid issues"
+ gunicorn --chdir /usr/src/app app_sidebar_collapsible:server
+ # tail -f /dev/null
+fi