How to Deploy a Django Project With Nginx and Gunicorn

How to Deploy a Django Project With Nginx and Gunicorn

643 VIEWS

· · ·

If you are looking to deploy a Django project with Nginx and Gunicorn, first you need to understand the basics.

Django is an open-source web application framework that lets you build complex websites and web services quickly and efficiently. You write Django in Python, meaning that if you’ve got some knowledge of this programming language, you can start using it almost immediately.

Nginx and Gunicorn are two popular open-source web servers. In this guide, I’ll teach you how to install and use Nginx and Gunicorn on Ubuntu 22.04 LTS, the latest version of Ubuntu at the time of writing. This guide is beginners friendly. We’ll be making a new virtualenv to create a clean project environment. Then, I’m going to show you how we can deploy a Django project with Nginx and Gunicorn.

Installation and Virtual Environment

Let’s start by connecting to our Ubuntu server and updating the current packages installed on the server.

sudo apt update

Next, we will download and install Nginx, Pip, VirtualEnv and curl from Ubuntu Repositories. We will download the remaining packages from Python Package Index (PyPI).

sudo  apt  install nginx python3-pip python3-virtualenv curl

Before cloning the Django project from Github, we will create a folder called nginx-django, a new virtual environment, and activate the new virtual environment. Let’s create and switch to the new folder.

mkdir nginx-django
cd nginx-django

The new folder will contain the cloned Django project and the new virtual environment. Let’s create and activate the virtual environment.

virtualenv env
source env/bin/activate

Cloning From GitHub 

Now that the virtual environment is ready, we can clone the project from Github.

git clone https://github.com/isaiaholadapo/nginx-tutorial.git

The project is cloned into a folder called nginx-tutorial, so let’s switch to this folder and install the project requirements.

cd nginx-tutorial
pip install -r requirements.txt

To access the project from our PC, we need to edit the project settings.py file and allow external connections to the project. Let’s locate line 28, which contains the ALLOWED_HOSTS = []. In the square bracket, we can add all the domains or IPs that will have access. If we want to open it to everyone, we can use an asterisk. For this tutorial, we will use an asterisk.

nano nginxtutorial/settings.py

The command above will open the vim editor. Scroll down till you locate the ALLOWED_HOSTS = [] and change it to ALLOWED_HOSTS = ['*']. Press control + o to save changes and control + x to exist.

We will need to run the migration, collect static and create a super user using the code snippets below.

python manage.py migrate
python manage.py collectstatic
python manage.py createsuperuser

This is the last phase of our project setup. We will run the project server before running the server and confirm that port 8000 is on your hosting server. We will use 0.0.0.0 as the host so that we can access the project from your server IP.

python manage.py runserver 0.0.0.0:8000

From your PC server type the snippet below to access the project.

http://your_server_public_ip:8000

The Django default project page should show on your browser. Press `control + c` to stop the server from running.

Gunicorn

Gunicorn will serve the project. It will allow the project to run without using Django python manage.py runserver command. Let’s install it using pip.

pip install gunicorn

Let’s serve the project using Gunicorn.

gunicorn --bind 0.0.0.0:8000 nginxtutorial.wsgi

Confirm that the application is running from your browser using the URL below:

http://your_server_public_ip:8000

Let’s stop the Gunicorn using control + c and deactivate the virtual environment before moving to the next step.

deactivate

Socket File

To improve how the project server is started and stopped, we’ll create a systemd socket file that will listen for incoming connections so that Gunicorn will handle the connection. Let’s create a socket file using sudo.

sudo nano /etc/systemd/system/nginxtutorial.socket

This will open a text editor. Paste the code snippet below:

[Unit]
Description=nginxtutorial socket

[Socket]
ListenStream=/run/nginxtutorial.sock

[Install]
WantedBy=sockets.target

In the code snippet above, the unit section describes the socket, while the socket section contains the sock file location and the install section ensures that the file is created.

Next, we will create the nginxtutorial.service file using sudo.

sudo nano /etc/systemd/system/nginxtutorial.service

In the text editor window, paste the code snippet below:

[Unit]
Description=nginxtutorial daemon
Requires=nginxtutorial.socket
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/nginx-django/nginx-tutorial
ExecStart=/home/ubuntu/nginx-django/env/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/nginxtutorial.sock \
          nginxtutorial.wsgi:application

[Install]
WantedBy=multi-user.target

We have successfully created the service file. Confirm that the WorkingDirectory and ExecStart path is your project path. Let’s start, enable and check the status of the socket file.

sudo systemctl start nginxtutorial.socket
sudo systemctl enable nginxtutorial.socket
sudo systemctl status nginxtutorial.socket

You should get a message that tells you it’s active and listening. If you receive any error message, you can check the socket log using:

sudo journalctl -u nginxtutorial.socket

Let’s confirm the sock file using the code snippet below.

file /run/nginxtutorial.sock

The nginxtutorial.service file is not yet active because no connection has been received yet. When you check the status using the code snippet below, its status will be nginxtutorial.service.

sudo systemctl status  nginxtutorial

Activating the Service File

Let’s activate it by sending a connection using curl.

curl --unix-socket /run/nginxtutorial.sock localhost

An HTML output will be returned. This means that Gunicorn has been started, and it can serve the project. If you didn’t get the HTML output, check its logs using:

sudo journalctl -u nginxtutorial

Also, check that the service file /etc/systemd/system/nginxtutorial.service is properly configured. If you edit the file, you will need to reload the daemon and restart the Gunicorn.

sudo systemctl daemon-reload
sudo systemctl restart nginxtutorial

You can confirm its status using:

sudo systemctl status  nginxtutorial

Nginx

Let’s configure Nginx by creating a server block in the sites-available directory.

sudo nano /etc/nginx/sites-available/nginxtutorial

Inside the text editor, let’s type the code snippet below:

server {
    listen 80;
    server_name your_server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/ubuntu/nginx-django/nginx-tutorial;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/nginxtutorial.sock;
    }
}

Note: Ensure to replace the server_domain_or_IP with your domain or server IP. The root should contain your project directory path.

Let’s link it to the `sites-enabled` directory using:

sudo ln -s /etc/nginx/sites-available/nginxtutorial /etc/nginx/sites-enabled

Let’s test the configuration so that we can be sure that everything is working correctly.

sudo nginx -t

If you get a success message, you will need to restart nginx using:

sudo systemctl restart nginx

But if you get an error message, check your configuration in sudo nano /etc/nginx/sites-available/nginxtutorial and you can also check the error logs using:

sudo tail -F /var/log/nginx/error.log

You can access your project using your server IP or domain. If you want to use your domain, ensure that the domain is linked to your server.

Troubleshooting

If your CSS and JavaScript files are not loaded, you can edit the nginx.conf file and change the www-data to your server username e.g. ubuntu.

sudo nano /etc/nginx/nginx.conf

Whenever you edit your project code, you will need to restart the Gunicorn process so that the changes can reflect on your website.

sudo systemctl restart nginxtutorial

If you edit the socket or service files, you need to reload the daemon, and the process restarts.

sudo systemctl daemon-reload
sudo systemctl restart nginxtutorial.socket nginxtutorial.service

Whenever the Nginx server block is edited:

sudo nginx -t && sudo systemctl restart nginx

If you want to view Nginx error logs:

sudo less /var/log/nginx/error.log

Conclusion

We started by preparing our virtual environment and installing the virtualenv package via pip. We then created a virtual environment in the directory where the Django project was and activated it. The next step was to get our Django project ready to be served by Gunicorn and Nginx. Finally, we configured Gunicorn to get it ready to serve requests from Nginx and then configured Nginx using Gunicorn as a proxy to make all of this work.

If you are curious about what else you can do with Django, take a look at this article on using the Django REST framework to serialize data


I am a Python Developer with experience in web development using Django, Flask, REST API, SQL, HTML, CSS, JavaScript, AWS and Git. I also write technical articles where I explain web development and software engineering.


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published.

Menu
Skip to toolbar