Install python 3
sudo apt-get update
Sudo apt-get install python3
Sudo apt-get install python3-pip
Create a alias for python3
Add the below line into .bash_aliases file under home/user folder:
alias python=python3
Run
source .bash_aliases
Install dash and other modules needed. Note it needs the 'sudo' otherwise it installs to the user's .local/bin folder.
Sudo pip install dash
...
Python helloworld.py
Note, dash app must have the app as dash_app.server to be able to be picked up by gunicorn
from dash import Dash, html, dcc
import plotly.express as px
import pandas as pd
dash_app = Dash(__name__)
app = dash_app.server
df = pd.DataFrame({
"X": [1, 2, 3, 4, 5],
"y": [2, 4, 6, 4, 7]
})
fig = px.bar(df, x="X", y="y")
dash_app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='A test div'),
dcc.Graph(
id='1',
figure=fig
)
])
if __name__ == '__main__':
dash_app.run_server(debug=True)
Sudo pip install gunicorn
The gunicorn command will be available in
/usr/local/bin/gunicorn
Note it needs to run under sudo otherwise it installs to the home folder.
To run dash app from gunicorn, use the command below. Need to use the full path of gunicorn. Helloworld is the python file name. "app" is the flask instance from dash_app.server
/usr/local/bin/gunicorn -b 0.0.0.0:8080 helloworld:app
If not running from the directory that contains the helloworld.py, use --chdir to set the folder:
/usr/local/bin/gunicorn -b 0.0.0.0:9090 --chdir /home/user/dash helloworld:app
Run as a service
The linux Systemd service seems not available in WSL so it needs a different way to start gunicorn automatically on start up. Also WSL is not by default started by windows start up either. A way seems working is registering the wsl command line as a service using NSSM so it automatically starts wsl command to run the gunicorn command.
wsl -e /usr/local/bin/gunicorn -b 0.0.0.0:9090 --chdir /mnt/d/dash helloworld:app
The -e is for executing linux command. "bash.exe -c thecommand ..." works too. Note the WSL automatically mount the c, d, e. etc. drives in the windows system and give it label c, d, e. etc. so you don't need to copy the code into the linux file system to run. The code can be sitting in windows D drive and then gunicorn can read the code through /mnt/d/. The NSSM setup is as follows:
application path: c:\windows\system32\wsl.exe
startup directory: c:\windows\system32
arguments: -e /usr/local/bin/gunicorn -b 0.0.0.0:9090 --chdir /mnt/d/dash helloworld:app
Important: On the 'Log On' tag, choose the user account that has installed the linux instance with WSL. The reason is a linux instance e.g. ubuntu is installed for a specific user (unless installed for all users including the Local System user, possible?). The above wsl command needs to run under that account to access the linux instance so the Log On user must be specified otherwise the service will fail.
An alternative way to register wsl as a service is using the SC.EXE comes with windows. Simply run the below from command line:
sc.exe create dash-app-service binpath= "c:\windows\system32\wsl.exe -e /usr/local/bin/gunicorn -b 0.0.0.0:9091 --chdir /home/dash/ helloworld:app" obj= accountname password= password
Note there is a space after the parameter, i.e. "binpath= "
Install Microsoft SQL ODBC driver and Pyodbc
Add microsoft key. Switch to root account and then curl the key file
Sudo su
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
Download the repo file.
curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
Note to select the right version of the Ubuntu in the url.
Now install the driver.
Sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
Now install the pre-requisite for pyodbc
Sudo apt-get install -y unixodbc-dev
Install pyodbc
sudo pip install pyodbc
Now can use "Driver={ODBC Driver 18 for SQL Server}" in pyodbc connection. Test it in python:
import pyodbc
conn_str = "Driver={ODBC Driver 18 for SQL Server};Server=database url;Database=MAC;uid=usre;pwd=password"
conn = pyodbc.connect(conn_str)
conn.close()