Gunicorn ‘Green Unicorn’ is a fast and lightweight Python web server for UNIX applications. It is compatible with various web frameworks like WSGI, Django, and Paster. Gunicorn has a simple Python configuration, multiple worker configurations, and various server hooks for complexity. Nginx is an open-source web server that can be used as a reverse proxy server, mail proxy, HTTP cache, and load balancer.

It is rare to use a WSGI server and a web server to host a web application but you can use Gunicorn and Nginx together. Nginx receives and handles requests coming from the internet and according to how it is configured it only passes the requests that are relevant to the web application to Gunicorn. Gunicorn on the other hand converts the requests received from Nginx into a format which your web application can handle. Nginx takes care of domain name routing, serves static files, and takes a lot of requsets at once while Gunicorn is optimized to execute your code, translate requests to WSGI compatible then to proper HTTP responses for your web application.

Flask is a Web framework written in Python that is used in developing Web applications, Web APIs, and Machine learning applications. It is mostly referred to as s micro-framework as it does not require any particular libraries or tools to function. It also does not include extra components but third-party libraries can be added. It is quick to get started and if you understand Python it is easy to create end-to-end projects. It is best known for building lightweight web applications and small static websites.

Some of the key features are:

  • Restful Request Handling
  • Fast Debugging
  • Flexible configuration
  • Application Programming Interface
  • Integrated Unit Testing

Major Applications that have been developed with Flask include LinkedIn, Pinterest, Reddit, Uber, Netflix, Lyft, etc.

This guide will show you how to install Flask with Gunicorn and Nginx on CentOS 9 / AlmaLinux 9.

Setup the environment

First, enable the EPEL repository:

sudo dnf config-manager --set-enabled crb
sudo dnf install epel-release epel-next-release

Update your system packages:

sudo dnf update -y

Install other dependency packages.

sudo dnf install python3-pip python3-devel gcc

Create a Python virtual environment by first installing the virtual environment package.

sudo pip install virtualenv

Check that the virtual environment was installed successfully by checking the version:

$ virtualenv --version
virtualenv 20.16.0 from /usr/local/lib/python3.9/site-packages/virtualenv/__init__.py

Create a directory to store the Projects then change it to that directory.

mkdir ~/newproject
cd ~newproject

Now create a Python virtual environment to store the Flask Project Python requirements.

$ virtualenv newprojectenv
created virtual environment CPython3.9.10.final.0-64 in 480ms
  creator CPython3Posix(dest=/home/technixleo/newproject/newprojectenv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/technixleo/.local/share/virtualenv)
    added seed packages: pip==22.2, setuptools==63.2.0, wheel==0.37.1
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator

Activate the environment to install applications.

source newprojectenv/bin/activate

Your Prompt will change and it will resemble something similar to (newprojectenv) [[email protected] newproject]

Setup Flask Application with Gunicorn

In your virtual environment install Flask and Gunicorn with pip.

$ pip install gunicorn flask
...
Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.2.0 click-8.1.3 flask-2.1.3 gunicorn-20.1.0 importlib-metadata-4.12.0 itsdangerous-2.1.2 zipp-3.8.1

Now let’s create a sample application. Create a new Python file and give it a name, say newproject.py

vi ~/newproject/newproject.py

Import Flask and instantiate a Flask object.

from flask import Flask
application = Flask(__name__)

@application.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There! This is Technixleo sample application.</h1>"

if __name__ == "__main__":
    application.run(debug=True,host='0.0.0.0')

Save and close the file.

Test your Flask by using the following command.

$ python newproject.py
 * Serving Flask app 'newproject' (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: on
 * Running on all addresses (0.0.0.0)
   WARNING: This is a development server. Do not use it in a production deployment.
 * Running on http://127.0.0.1:5000
 * Running on http://192.168.200.42:5000 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 

Then visit your browser with the URL provided to see something similar to this:

You can stop the process with Ctrl+C.

Create WSGI entry point

Create a Python file that will be used as an entry point for the application by Gunicorn.

vi ~/newproject/wsgi.py

Add the following details to the file.

from newproject import application

if __name__ == "__main__":
    application.run()

Let’s test the ability of Gunicorn to serve the project.

$ gunicorn --bind 0.0.0.0:5000 wsgi
[2022-07-26 14:50:19 +0300] [9264] [INFO] Starting gunicorn 20.1.0
[2022-07-26 14:50:19 +0300] [9264] [INFO] Listening at: http://0.0.0.0:5000 (9264)
[2022-07-26 14:50:19 +0300] [9264] [INFO] Using worker: sync
[2022-07-26 14:50:19 +0300] [9265] [INFO] Booting worker with pid: 9265

You would still access the web on http://localhost:5000.

Deactivate the virtual environment with the following command.

deactivate

Create a Systemd Unit File

Create a system file that runs Gunicorn as a service.

sudo vi /etc/systemd/system/newproject.service

Then append the following details to the file.

[Unit]
Description=Gunicorn instance to serve newproject
After=network.target

[Service]
User=technixleo
Group=nginx
WorkingDirectory=/home/technixleo/newproject
Environment="PATH=/home/technixleo/newproject/newprojectenv/bin"
ExecStart=/bin/bash -c 'source /home/newproject/newprojectenv/bin/activate; gunicorn -w 3 --bind unix:newproject.sock -m 007 wsgi'

[Install]
WantedBy=multi-user.target

These set the Environment= variable which should lead to the bin directory inside your virtual environment. The ExecStart= path should lead where Gunicorn is installed in the virtual environment. Remember to replace the user ‘technixleo’ with the actual user on your system. Save and Exit the file.

Now start and enable the Gunicorn service.

sudo systemctl start newproject
sudo systemctl enable newproject

Configure Nginx

Install and enable the Nginx service.

sudo dnf install nginx
sudo systemctl enable nginx
sudo systemctl start nginx

Check to see if Nginx is running.

$ systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor pre>
     Active: active (running) since Tue 2022-07-26 11:38:02 EAT; 7s ago
    Process: 7438 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, stat>
    Process: 7439 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCES>
    Process: 7440 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
   Main PID: 7441 (nginx)
      Tasks: 3 (limit: 48809)
     Memory: 2.8M
        CPU: 21ms
     CGroup: /system.slice/nginx.service
             ├─7441 "nginx: master process /usr/sbin/nginx"
             ├─7442 "nginx: worker process"
             └─7443 "nginx: worker process"

Open the Nginx configuration file to create the server block/virtual host in Nginx.

sudo vi /etc/nginx/nginx.conf

Add the server and location block as shown below.

server {
    listen 80;
    server_name web.example.com www.web.example.com;

     location / {
        proxy_pass http://unix:/home/technixleo/newproject/newproject.sock;
    }
}

Save and close the file.

Check the Nginx configuration file for any errors:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart the service.

sudo systemctl restart nginx

Edit the host’s file to access the web application with your IP address.

$ sudo vi /etc/hosts
192.168.200.42 web.example.com

Save and exit the file. Go to http://newproject which is the server name on the file to access the application.

Conclusion

Flask is based on the WSGI Framework with full flexibility and minimalistic design. Use Flask if you like reading Python code and if your web applications are based on NoSQL. Gunicorn and Nginx web servers have convenient features that allow them to work together to host a web application. This guide has shown you how to install Flask with Gunicorn and Nginx on CentOS 9 / AlmaLinux 9.

Here is a list of other articles in our website:

LEAVE A REPLY

Please enter your comment!
Please enter your name here