How to serve a Flask application with uWSGI and Nginx
Introduction
This is a simple introduction on how to serve a Python Flask application with uWSGI and Nginx on Ubuntu.
Prerequisite
Install Nginx and Python:
sudo apt-get update
sudo apt-get install python3-pip python3-dev nginx
pip3 install uwsgi flask
Create a basic Flask application
mkdir /var/www/html/my_app
cd /var/www/html/my_app
Create a file app.py
with:
#!/usr/bin/python3
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return """
Welcome to my website!<br /><br />
<a href="/hello">Go to hello world</a>
"""
@app.route("/hello")
def hello():
return """
Hello World!<br /><br />
<a href="/">Back to index</a>
"""
if __name__ == '__main__':
# Will make the server available externally as well
app.run(host='0.0.0.0')
Test your application with flask built-in web server
Flask has a built in web server which you can use for test purposes. Just run:
python3 app.py
# * Serving Flask app "app.py"
# * Environment: production
# WARNING: Do not use the development server in a production environment.
# Use a production WSGI server instead.
# * Debug mode: off
# * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Alternatively, you can also use:
FLASK_APP=app.py flask run --host=0.0.0.0
And visit http://127.0.0.1:5000/.
Once you are able to confirm that your Flask application is up and running with the development web server, it is time to configure uWSGI and Nginx.
Configure uWSGI
In the same directory, create a file wsgi.py
with:
#!/usr/bin/python3
from app import app as application
if __name__ == "__main__":
application.run()
You can then test uWSGI:
uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi
And visit http://127.0.0.1:8000/.
Create a uWSGI Configuration File
Also in your project directory, create a file app.ini
with:
[uwsgi]
module = wsgi
socket = my_app.sock
chmod-socket = 660
vacuum = true
master = true
processes = 10
die-on-term = true
You can test the app.ini file with:
/usr/local/bin/uwsgi --ini /var/www/html/my_app/app.ini
Change the project directory ownership to www-data
chown -R www-data.www-data /var/www/html/my_app
Create a uWSGI startup file
Then create a systemctl startup file /etc/systemd/system/my_app.service
:
[Unit]
Description="uWSGI server instance for my_app"
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/html/my_app/
Environment=FLASK_ENV=test
ExecStart=/usr/local/bin/uwsgi --ini /var/www/html/my_app/app.ini
[Install]
WantedBy=multi-user.target
Start the process:
sudo systemctl start my_app
# Check the status
sudo systemctl status my_app.service
# You should be able to see the socket with
ls /var/www/html/my_app/my_app.sock
# /var/www/html/my_app/my_app.sock
# Enable it on startup
sudo systemctl enable my_app
Configure Nginx
Create a file /etc/nginx/sites-enabled/my_app
:
server {
listen 80;
server_name myapp.com www.myapp.com; # Replace with the actual domain name
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/html/my_app/my_app.sock;
}
}
Test your Nginx configuration and restart Nginx:
nginx -t -c /etc/nginx/nginx.conf
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
/etc/init.d/nginx restart
You are all set, just visit the domain in your browser!