0

I am currently using Plotly Dash, Python Flask to make an simple app. And I am deploying this app with azure. When I deploy the app with azure, it is causing errors saying:

2022-08-18T11:23:57.750944156Z: [ERROR] [2022-08-18 11:23:57 +0000] [77] [INFO] Reason: App failed to load.'

The entire Azure Error Log looks like the following:

    2022-08-18T11:23:34.797241866Z: [INFO]  
2022-08-18T11:23:34.797273866Z: [INFO]    _____                               
2022-08-18T11:23:34.797279966Z: [INFO]    /  _  \ __________ _________   ____  
2022-08-18T11:23:34.797284666Z: [INFO]   /  /_\  \___   /  |  \_  __ \_/ __ \ 
2022-08-18T11:23:34.797289266Z: [INFO]  /    |    \/    /|  |  /|  | \/\  ___/ 
2022-08-18T11:23:34.797361167Z: [INFO]  \____|__  /_____ \____/ |__|    \___  >
2022-08-18T11:23:34.797366667Z: [INFO]          \/      \/                  \/ 
2022-08-18T11:23:34.797371067Z: [INFO]  
2022-08-18T11:23:34.797375168Z: [INFO]  A P P   S E R V I C E   O N   L I N U X
2022-08-18T11:23:34.797379368Z: [INFO]  
2022-08-18T11:23:34.797383268Z: [INFO]  Documentation: http://aka.ms/webapp-linux
2022-08-18T11:23:34.797387368Z: [INFO]  Python 3.9.7
2022-08-18T11:23:34.797391468Z: [INFO]  Note: Any data outside '/home' is not persisted
2022-08-18T11:23:35.482343749Z: [INFO]  Starting OpenBSD Secure Shell server: sshd.
2022-08-18T11:23:35.612695990Z: [INFO]  App Command Line not configured, will attempt auto-detect
2022-08-18T11:23:35.968698946Z: [INFO]  Starting periodic command scheduler: cron.
2022-08-18T11:23:35.969417355Z: [INFO]  Launching oryx with: create-script -appPath /home/site/wwwroot -output /opt/startup/startup.sh -virtualEnvName antenv -defaultApp /opt/defaultsite
2022-08-18T11:23:36.061720088Z: [INFO]  Found build manifest file at '/home/site/wwwroot/oryx-manifest.toml'. Deserializing it...
2022-08-18T11:23:36.069520092Z: [INFO]  Build Operation ID: |OVJwTlsB6Wc=.6e98f261_
2022-08-18T11:23:36.070457005Z: [INFO]  Oryx Version: 0.2.20220308.4, Commit: c92fa6a2d6fc14dc9646f80e2bb2e393a5cdc258, ReleaseTagName: 20220308.4
2022-08-18T11:23:36.071003512Z: [ERROR]  Output is compressed. Extracting it...
2022-08-18T11:23:36.079174921Z: [ERROR]  Extracting '/home/site/wwwroot/output.tar.gz' to directory '/tmp/8da810b35d81226'...
2022-08-18T11:23:50.491449678Z: [ERROR]  App path is set to '/tmp/8da810b35d81226'
2022-08-18T11:23:50.600493509Z: [ERROR]  Detected an app based on Flask
2022-08-18T11:23:50.601316020Z: [ERROR]  Generating `gunicorn` command for 'app:app'
2022-08-18T11:23:50.658830975Z: [INFO]  Writing output script to '/opt/startup/startup.sh'
2022-08-18T11:23:50.764784165Z: [INFO]  Using packages from virtual environment antenv located at /tmp/8da810b35d81226/antenv.
2022-08-18T11:23:50.765624276Z: [INFO]  Updated PYTHONPATH to ':/opt/startup/app_logs:/opt/startup/code_profiler:/tmp/8da810b35d81226/antenv/lib/python3.9/site-packages'
2022-08-18T11:23:52.485287934Z: [ERROR]  [2022-08-18 11:23:52 +0000] [77] [INFO] Starting gunicorn 20.1.0
2022-08-18T11:23:52.534277677Z: [ERROR]  [2022-08-18 11:23:52 +0000] [77] [INFO] Listening at: http://0.0.0.0:8000 (77)
2022-08-18T11:23:52.541304169Z: [ERROR]  [2022-08-18 11:23:52 +0000] [77] [INFO] Using worker: sync
2022-08-18T11:23:52.564437272Z: [ERROR]  [2022-08-18 11:23:52 +0000] [80] [INFO] Booting worker with pid: 80
2022-08-18T11:23:57.218301803Z: [ERROR]  Application object must be callable.
2022-08-18T11:23:57.219280817Z: [ERROR]  [2022-08-18 11:23:57 +0000] [80] [INFO] Worker exiting (pid: 80)
2022-08-18T11:23:57.220215831Z: [INFO]  Hello
2022-08-18T11:23:57.742512931Z: [ERROR]  [2022-08-18 11:23:57 +0000] [77] [INFO] Shutting down: Master
2022-08-18T11:23:57.750944156Z: [ERROR]  [2022-08-18 11:23:57 +0000] [77] [INFO] Reason: App failed to load.

This is the used requirements.txt:

Brotli==1.0.9
click==8.1.3
colorama==0.4.5
dash==2.6.1
dash-core-components==2.0.0
dash-html-components==2.0.0
dash-table==5.0.0
Flask==2.2.2
Flask-Compress==1.12
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
plotly==5.10.0
tenacity==8.0.1
Werkzeug==2.2.2

Lastly, here is my app.py code that I am trying to deploy:

# pylint: disable=missing-docstring
import dash
from dash import html, dcc, Output, Input
from dash.exceptions import PreventUpdate

print("Hello")

app = dash.Dash(__name__)
print("9")
app.layout = html.Div(
    [
        dcc.Input(id="value", placeholder="my-value"),
        html.Div(["You entered: ", html.Span(id="out")]),
        html.Button("style-btn", id="style-btn"),
        html.Div("style-container", id="style-output"),
    ]
)

print("19")
@app.callback(Output("out", "children"), Input("value", "value"))
def on_value(value):
    if value is None:
        print(value)
        raise PreventUpdate

    return value

print("28")
@app.callback(Output("style-output", "style"), [Input("style-btn", "n_clicks")])
def on_style(value):
    if value is None:
        raise PreventUpdate

    return {"padding": "10px"}

print("36")
# if __name__ == "__main__":
print("38")
app.run_server(debug=True, port=8000)

I am not really sure what is causing the mentioned errors while deploying the app on azure. Any help is highly appreciated.

1 Answers1

0

Okay, I took a look at the issue and there are a couple tweaks you need to make to get it to work. The first is related to the port you have defined. I am assuming you aren't building a container first and just publishing directly. Know, that it is running a container behind the scenes so the port requirements listed here still apply. So set the port as either 80, 8080, or set the app setting specificed above to your custom port.

The second issue is what Azure expects. It expects your entry point to be application or app in both the Python file name and inside of your Python file. Since Dash is wrapping Flask, you need to make some tweaks to make sure that the app variable is the Flask server. I did a blog post about it here

Here is the changes that I got to work. Lines 8 and 10 are the keys ones.

# pylint: disable=missing-docstring
import dash
from dash import html, dcc, Output, Input
from dash.exceptions import PreventUpdate

print("Hello")

dash_app = dash.Dash(__name__)
print("9")
app = dash_app.server


dash_app.layout = html.Div(
    [
        dcc.Input(id="value", placeholder="my-value"),
        html.Div(["You entered: ", html.Span(id="out")]),
        html.Button("style-btn", id="style-btn"),
        html.Div("style-container", id="style-output"),
    ]
)

print("19")
@dash_app.callback(Output("out", "children"), Input("value", "value"))
def on_value(value):
    if value is None:
        print(value)
        raise PreventUpdate

    return value

print("28")
@dash_app.callback(Output("style-output", "style"), [Input("style-btn", "n_clicks")])
def on_style(value):
    if value is None:
        raise PreventUpdate

    return {"padding": "10px"}

print("36")

if __name__ == "__main__":
    print("38")
    dash_app.run_server(debug=True, port=80)
Jamie
  • 3,094
  • 1
  • 18
  • 28