0

I am relatively new to deploying python web applications but I was trying to deploy my H2O wave app to Heroku but kept running into issues and I couldn't find much help in the documentation.

Everything works fine locally if I start the server using the command (in the SDK for wave):

$ ./waved
2021/01/22 10:26:38 # 
2021/01/22 10:26:38 # ┌─────────────────────────┐
2021/01/22 10:26:38 # │  ┌    ┌ ┌──┐ ┌  ┌ ┌──┐  │ H2O Wave
2021/01/22 10:26:38 # │  │ ┌──┘ │──│ │  │ └┐    │ 0.11.0 20210118061246
2021/01/22 10:26:38 # │  └─┘    ┘  ┘ └──┘  └─┘  │ © 2020 H2O.ai, Inc.
2021/01/22 10:26:38 # └─────────────────────────┘
2021/01/22 10:26:38 # 
2021/01/22 10:26:38 # {"address":":10101","t":"listen","webroot":"/Users/kenjohnson/Documents/TTT/H2O Wave/wave/www"}
2021/01/22 10:26:39 # {"addr":"127.0.0.1:64065","route":"/tennis-pred","t":"ui_add"}
2021/01/22 10:46:04 # {"host":"http://127.0.0.1:8000","route":"/counter","t":"app_add"}

then in the root directory of the project running:

uvicorn tennis_pred_app:main

For deployment, all I have other than my wave python file is a requirements.txt and a Procfile:

web: uvicorn tennis_pred_app:main --host 0.0.0.0 --port 10101

this is what my foo (tennis_pred_app.py) looks like (simplified):

from h2o_wave import Q, main, app, ui

@app("/tennis-pred")
async def serve(q: Q):
    show_form(q)
    await q.page.save()

The error I am currently running into is:

2021-01-22T00:28:41.000000+00:00 app[api]: Build started by user x
2021-01-22T00:31:07.040695+00:00 heroku[web.1]: State changed from crashed to starting
2021-01-22T00:31:06.879674+00:00 app[api]: Deploy 1dc65130 by user x
2021-01-22T00:31:06.879674+00:00 app[api]: Release v23 created by user x
2021-01-22T00:31:26.580199+00:00 heroku[web.1]: Starting process with command `uvicorn tennis_pred_app:main --host 0.0.0.0 --port 20819`
2021-01-22T00:31:30.299421+00:00 app[web.1]: INFO:     Uvicorn running on http://0.0.0.0:20819 (Press CTRL+C to quit)
2021-01-22T00:31:30.299892+00:00 app[web.1]: INFO:     Started parent process [4]
2021-01-22T00:31:46.000000+00:00 app[api]: Build succeeded
2021-01-22T00:32:27.041954+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2021-01-22T00:32:27.093099+00:00 heroku[web.1]: Stopping process with SIGKILL
2021-01-22T00:32:27.199933+00:00 heroku[web.1]: Process exited with status 137
2021-01-22T00:32:27.242769+00:00 heroku[web.1]: State changed from starting to crashed
Ken
  • 1,155
  • 2
  • 19
  • 36
  • This is weird. Your logs say "Uvicorn running on http://0.0.0.0:33594", which I'd guess is the right port as it changes every time, but it also says your app isn't binding to the port. – ChrisGPT was on strike Jan 22 '21 at 00:46
  • Yes, it is weird since it is working fine on the localhost, and the only thing I've added is the Procfile – Ken Jan 22 '21 at 00:49
  • Can you show your `foo.py`, please? – ChrisGPT was on strike Jan 22 '21 at 00:51
  • Your `Procfile` says `foo:main`. You say your `foo.py` is actually `tennis_pred_app.py`. The code snippet you showed has just one function: `serve`. So does your `Procfile` _actually_ say `web: uvicorn tennis_pred_app:serve --host 0.0.0.0 --port $PORT`? – ChrisGPT was on strike Jan 22 '21 at 01:10
  • Yes, I have used tennis_pred_app instead of foo and I had main instead of serve because of the documentation from the H2O wave website: https://h2oai.github.io/wave/docs/deployment and main and Q are both things I imported from the h2o_wave library (edited the above post again) – Ken Jan 22 '21 at 01:13

2 Answers2

3

You don't get to choose your port on Heroku. Instead, Heroku assigns you a port via the PORT environment variable.

Change your Procfile from

web: uvicorn foo:main --host 0.0.0.0 --port 10101

to

web: uvicorn foo:main --host 0.0.0.0 --port $PORT
ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
  • Thank you for the information, however even after making this change I am still getting the same error, do you have any more ideas? (I have added an image of the full error above) – Ken Jan 22 '21 at 00:37
  • You're still getting a boot timeout with an error that your process isn't binding to `$PORT`? That exact error message? – ChrisGPT was on strike Jan 22 '21 at 00:42
  • What is the reason why it needs to listen to a port? – Ken Jan 22 '21 at 00:45
  • Because that's how servers work. They listen for connections on (usually one) port. – ChrisGPT was on strike Jan 22 '21 at 00:47
  • One other thing I forgot to mention is that when I run locally, I need to start the server first by executing a ./waved command in the SDK package for wave, would I need to include this in my deployment as well? – Ken Jan 22 '21 at 17:56
  • don't mean to bother but could you take a look at this question? Same problem but I reworded it which may make it simpler to understand the problem: https://stackoverflow.com/questions/65888300/deploy-python-based-web-application-to-heroku – Ken Jan 25 '21 at 22:07
0

See this blog post for the exact guide.

More explanation for why the other answer is generally correct but does not apply to H2O Wave:

If you look at architecture, you may notice there are actually 2 servers included. The first is a python (uvicorn) one that is used for your Wave app - this is not exposed to the outside directly but uses a kind of a proxy server - the second server. This second (Golang) server communicates directly with a browser (outside) and thus should be started on the $PORT Heroku assigned to you, e.g. via the H2O_WAVE_LISTEN env variable - see other config options.

MartinT
  • 590
  • 5
  • 21