Python is among the popular programming languages. This general-purpose programming language is known for various purposes that include machine learning, software development, website development, data science, automation e.t.c
Flask is a lightweight Python framework that provides tools that simplify the creation of Python web applications. It offers extensibility and flexibility, with in-built modules that make the development process easy. As opposed to other Python modules like Django, Flask is easy to use since developers are able to build a web application even using a single file.
Flask makes use of the Jinja template engine that dynamically builds HTML pages with the familiar Python concepts that include lists, loops, variables e.t.c. Flask can be used to create both simple and large-scale applications. It is popularly used in the following areas:
- Portfolio Website
- Social Network Web App
- Blog App
- Weather App
- Rest API App
- Deploying Machine Learning models
- Feedback Form
There are several companies all over the world that use Flask to run their website-based businesses. These companies include Reddit, Uber, Netflix, LinkedIn, Airbnb, Pinterest, Uber, Mailgun, PythonAnyWhere e.t.c
This guide will deeply demonstrate how to install Flask with Gunicorn and Nginx on Rocky Linux 8 / AlmaLinux 8.
Step 1 – Install Required Packages
We will begin by installing the required packages. Some of these packages are provided in the EPEL repository which needs to be enabled:
sudo dnf -y install epel-release
Now install the required packages that include the Python package manager(PIP), a compiler, and the Python development package required by Gunicorn.
sudo dnf install python3-pip python3-devel gcc -y
You also need to install Nginx which will be used for proxying:
sudo dnf install nginx -y
Step 2 – Create a Python Environment
A virtual Python environment is required in order to isolate this project from other available Python projects on the system. Using the install PIP, install virtualenv
sudo pip3 install virtualenv
Create a directory for the Flask project:
sudo su -
mkdir /myproject && cd /myproject
Create a virtual environment for the Python requirements.
virtualenv projectenv
This command starts a copy of PIP and Python in the projectenv directory. Activate the environment:
source projectenv/bin/activate
Step 3 – Configure the Flask Application
Once the environment has been activated, we are set to create a Python application using Flask. Begin by installing Flask and Gunicorn as shown;
pip3 install gunicorn flask
Proceed and create your application with Flask. Flask existing as a Python module can be easily imported and used to initialize a web application.
For example, in this guide, we will create an application as shown:
vim /myproject/hello.py
Add your code and import Flask as a module. For example:
from flask import Flask
application = Flask(__name__)
@application.route("/")
def hello():
return "<h1 style='color:green'>Hello World, Flask is amazing!</h1>"
if __name__ == "__main__":
application.run(host='0.0.0.0')
This is a simple web page, the content will be presented when the root domain is queried. Allow port 5000 through the firewall:
sudo firewall-cmd --add-port=5000/tcp --permanent
sudo firewall-cmd --reload
Test the application, by issuing the command:
$ python hello.py
* Serving Flask app 'hello' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://192.168.205.2:5000/ (Press CTRL+C to quit)
On the web server, using the presented port, you should be able to see this:
Step 4 – Configure Gunicorn
We will create a WSGI entry point that will instruct Gunicorn on how to interact with our created application. This file will be created as below:
vim /myproject/wsgi.py
We will simply import the Flask instance.
from hello import application
if __name__ == "__main__":
application.run()
Save the file and verify that Gunicorn is able to serve the application. Allow port 8080 through the firewall:
sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
We will specify the interface and port to be used. For example:
cd /myproject
gunicorn --bind 0.0.0.0:8080 wsgi
Now access the page using the URL http://IP_Address:8080
We have verified the functionality of Gunicorn. Now press CTRL+C and deactivate the virtual environment.
deactivate
Step 5 – Create a Systemd Service file
To be able to automatically start the Gunicorn and serve the Flask application on system boot, we need to create a systemd service file.
The service file can be created as shown:
sudo vim /etc/systemd/system/myapp.service
In the file, define the below lines:
[Unit]
Description=The Gunicorn instance to serve Flask Project
After=network.target
[Service]
WorkingDirectory=/myproject
Environment="PATH=/myproject/projectenv/bin"
ExecStart=/myproject/projectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi
[Install]
WantedBy=multi-user.target
Remember to replace /myproject with the actual path of your project created in step 2. Gunicorn will create a Unix socket called myproject.sock with a umask value of 007. Save the file and configure SELinux for the paths above to be accessible:
chcon -R -t bin_t /myproject/projectenv/bin/
Reload the system daemon.
sudo systemctl daemon-reload
Start and enable the service to start automatically on boot:
sudo systemctl start myapp
sudo systemctl enable myapp
Verify if the service is running:
$ systemctl status myapp
● myapp.service - The Gunicorn instance to serve Flask Project
Loaded: loaded (/etc/systemd/system/myapp.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2022-09-30 23:00:22 EAT; 6s ago
Main PID: 4797 (gunicorn)
Tasks: 4 (limit: 49442)
Memory: 65.7M
CGroup: /system.slice/myapp.service
├─4797 /myproject/projectenv/bin/python /myproject/projectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi
├─4800 /myproject/projectenv/bin/python /myproject/projectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi
├─4801 /myproject/projectenv/bin/python /myproject/projectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi
└─4803 /myproject/projectenv/bin/python /myproject/projectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi
Sep 30 23:00:22 rocky8.mylab.io systemd[1]: Started The Gunicorn instance to serve Flask Project.
Sep 30 23:00:22 rocky8.mylab.io gunicorn[4797]: [2022-09-30 23:00:22 +0300] [4797] [INFO] Starting gunicorn 20.1.0
Sep 30 23:00:22 rocky8.mylab.io gunicorn[4797]: [2022-09-30 23:00:22 +0300] [4797] [INFO] Listening at: unix:myproject.sock (4797)
Sep 30 23:00:22 rocky8.mylab.io gunicorn[4797]: [2022-09-30 23:00:22 +0300] [4797] [INFO] Using worker: sync
Sep 30 23:00:22 rocky8.mylab.io gunicorn[4800]: [2022-09-30 23:00:22 +0300] [4800] [INFO] Booting worker with pid: 4800
Sep 30 23:00:22 rocky8.mylab.io gunicorn[4801]: [2022-09-30 23:00:22 +0300] [4801] [INFO] Booting worker with pid: 4801
Sep 30 23:00:22 rocky8.mylab.io gunicorn[4803]: [2022-09-30 23:00:22 +0300] [4803] [INFO] Booting worker with pid: 4803
Step 6 – Configure the Nginx Proxy
The Nginx web server is used to proxy pass the HTTP requests. We will also capture additional HTTP headers for Gunicorn to obtain some information about the client.
Since Nginx has already been installed, create a Virtualhost file for the application:
sudo vim /etc/nginx/conf.d/myapp.conf
In the file, add the below lines:
server {
listen 80;
server_name myapp.example.com;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/myproject/myproject.sock;
}
}
Remember to replace the server_domain_or_IP and /myproject/myproject.sock with the create Unix socket in the above step.
Save the file and allow the Nginx group to execute commands in the project directory:
sudo chgrp -R nginx /myproject/
Now check the syntax of the Nginx config:
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Start and enable Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
Configure SELinux to avoid the error “Nginx Permission denied while connecting to upstream”. This allows the Gunicorn sock to be accessed by Nginx:
sudo dnf install policycoreutils-python-utils -y
sudo semanage permissive -a httpd_t
Allow port 80 through the firewall;
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload
Access the application using the URL http://domain_name
Final Thoughts
The knowledge gathered here can now be used to create and use a Flask application with Gunicorn and Nginx. Flask is a lightweight and powerful Python module that can be used to develop web applications without much worry about structure and design. I hope this guide was able to help you.
See more:
How To Install NetBox IPAM on Rocky Linux 8 / CentOS 8
Install Python 3.9 on CentOS 8 / CentOS 7
Best Books To Learn Object Oriented Programming