Deploying Python Applications with Gunicorn
Gunicorn `Green Unicorn` is a pure Python HTTP server for WSGI applications, originally published by Benoit Chesneau on 20th February 2010. It’s a WSGI (Web Server Gateway Interface) HTTP server, a calling convention used for a group of web servers that forward requests to web applications or frameworks written in Python. So, in a nutshell, it’s an intermediary/interface between the web server and your python application.
Why do we need Gunicorn?
Now the problem is a python web application cannot be deployed on traditional web servers such as Apache because they are designed to serve static web pages created using HTML and CSS. Python web applications are more complex than static web pages, so you need a WSGI server like Gunicorn specifically intended for Python web applications and frameworks. If your application contains static content, you can usually use a server such as Nginx to serve the static content. An image demonstration will help to understand the role of a Gunicorn server more clearly.
As you see in the image above, Gunicorn is designed to work with web servers and Python web applications to perform the following tasks:
- How to communicate with a number of web several responding to lots of web requests at once and distributing the load.
- keeping up multiple processes of the web application running.
Some more features of Gunicorn:
- Gunicorn server is surprisingly well suited with python web frameworks like Django and Flask, Falcon, etc.
- It is mild on server resources and pretty rapid performance.
- It is often used with NGINX as a proxy in production environments.
How to deploy a Python Application with image widget Gunicorn?
Now that you have understood what Gunicorn is and what it does let’s see it in action by deploying a Django web application on a Ubuntu machine.
A Ubuntu machine as we will use a Ubuntu virtual machine running on Azure, you can go with any cloud service of your choice or you can even deploy it on a local machine.
Installing required packages
sudo apt install python3 python3-pip nginx
Above have installed Nginx,python3, and pip, As we will be using Nginx as a proxy and we obviously need python3 and pip package installer.
Setup a development environment for your project
This step can be skipped but it is always a good idea to use a dedicated development environment for each project, this can be achieved using a python virtual environment. To create one just run the following commands:
mkdir python_web_app; cd python_web_app
This will create a dedicated folder for the project, you can name it anything you want and cd (change directory) to go into your newly created directory then run the following command that will create a virtual environment for your project.
python3 -m venv venv ls
Now let’s activate the virtual environment and start using it.
By now you will have a virtual environment ready to be used, so let’s install Django and Gunicorn.
pip install django gunicorn
Create a Django Project and configure it for deployment:
Now you have all of the software and environment needed to start a Django project. Let’s create one by running the following commands.
django-admin startproject demo_project
I have an asterisk (‘*’) for the demo purpose you can add your desired domain names (don’t forget to add localhost).
We are done creating and configuring the Django default starter project, now run the following command
python3 manage.py runserver
If you see similar output as shown in the image then congrats you have successfully created a Django project which is live on your localhost at port 8000. If you encounter some warnings related to migrations just run the following commands,
python3 manage.py makemigrations python3 manage.py migrate
The warnings should be gone by now.
Using Gunicorn to serve the project.
In the previous step, we ran the project using Django in-built development server although it is not a deployment server only intended to be used while development. Let’s try Gunicorn to run the Django project, with the following commands:
gunicorn --bind 0.0.0.0:8000 demo_project.wsgi
This command binds Gunicorn with the WSGI interface of the Django project, and start listening for incoming request at port 8000.
Now everything is up and working, let us deploy the Django web app. First, deactivate the virtual environment by running deactivate in the terminal.
Creating system Socket and Service files for Gunicorn
Now that you’ve tested that Gunicorn with your Django application, you should implement a more robust way of starting and stopping the application server. To accomplish this, we will create systemd service and socket files, by running the following commands.
sudo nano /etc/systemd/system/gunicorn.socket
This will open the system socket file for Gunicorn with sudo privileges, add the following stuff to the file, create a [Unit] section to describe the socket, a [Socket] section to define the socket location, and a [Install] section to make sure the socket is created at the right time, once done just save and close the file.
[Unit] Description=gunicorn socket [Socket] ListenStream/run/gunicorn.sock [Install] WantedBy=sockets.target
sudo nano /etc/systemd/system/gunicorn.service
Now, let’s create and open a systemd service file for Gunicorn (the filename should match the socket filename) and add the following content to the file. It should look something like this.
As you can see It contains 3 sections :
- [Unit]: This is used to specify metadata and dependencies.
- [Service]: it specifies the user and group that you want the process to run under, also giving group ownership to the www-data group so that Nginx can communicate with Gunicorn.
- [Install]: This will tell systemd what to link this service to if you enable it to start at boot.
Enabling and checking socket and service files for Gunicorn.
The following commands will start running Gunicorn socket service and will enable it to start automatically on boot.
sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket
Check the status of the Gunicorn process to find out whether it was able to start
sudo systemctl status gunicorn
If something goes wrong you can see the logs for Gunicorn process by running the following command:
sudo journalctl -u gunicorn.socket
Configure Nginx proxy
Up till now, we are done with the hard part of setting up the Gunicorn and now we need to set up the Nginx server as a proxy that will handle all HTTP traffic and pass it to Gunicorn for processing. Start by creating a new server block in the Nginx site-available directory:
sudo nano /etc/nginx/sites-available/demo_project
As you can see, we have opened a server block in which we have specified that his block should listen on the 80 and that it should respond to the domain name you have provided.
In the location block, we have instructed to ignore any problems with finding a fav icon and have mapped the Nginx static path to the Django project static path.
Save and close the file when you are finished. Now, you can enable the file by linking it to the site-enabled directory:
sudo ln -s /etc/nginx/sites-available/demo_project /etc/nginx/sites-enabled
All done now just test the Nginx file for any syntax errors and restart the Nginx daemon.
sudo nginx -t sudo systemctl restart nginx
Please Login to comment...