Deploy Django Project on Ubuntu 16.04 Production Server step by step
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. It provides the developers a dedicated development server which is also known as testing server as well.Django in production is to run with Gunicorn and use Nginx as a reverse proxy so it gives more security to our application.In this post I will explain how one can run the Django application in the Production environment. So Let’s get started.
SSH & update ubuntu instance:
chmod 400 path-to-your-key.pem (for read permission)
ssh -i path-to-your-key.pem ubuntu@your-aws-instance-public-ip (We need to ssh into our EC2 instance)
sudo apt-get update && sudo apt-get upgrade -y
Setting up our project
We’ll be setting up our project in the default directory of nginx (/var/www/html). Here we can easily clone our project from service like github, bitbucket etc. For that we have to provide some permissions to our user.
sudo usermod -a -G www-data <username default is ubuntu>
sudo chown -R <username default is ubuntu>:www-data /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} +
find /var/www -type f -exec sudo chmod 0664 {} +
As we have cloned the git repo into var/www/html so this is our BASE_DIR for our django project. Right now we will be installing our required python packages into virtual environment.
sudo apt install python3-pip
sudo pip3 install virtualenv
virtualenv -p python3 venv # install it inside /var/www/html
sudo apt-get install python-dev python3-devActivate virtualenv from within /var/www/html using the command.
source venv/bin/activate
Then we will install the requirements for our project, and install gunicorn which is the key to running our application as a service within the server spontaneously.
Configuring Gunicorn
In production we won’t be using Django’s single-threaded development server, but a dedicated application server called Gunicorn.
- Install gunicorn in your application’s virtual environment
pip install gunicorn
- Test Sample Application with Gunicorn Server
Now that you have gunicorn, you can test whether it can serve your Django application by running the following command:
gunicorn website.wsgi:application — bind 0.0.0.0:8000
To configure gunicorn as a service, we will need to write a .service file within ubuntu’s system.
sudo nano /etc/systemd/system/gunicorn.service
Here, we will write a .service script to run gunicorn and create a .sock file within our project root directory. This .sock file will be accessed by Nginx to serve our application to the internet. A demo .service file:
File name: gunicorn.service -> This is also the name through which the gunicorn will be enabled as a service.
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/var/www/html
ExecStart=/var/www/html/gunicorn_start.sh
[Install]
WantedBy=multi-user.target
Now we have to edit the gunicorn_start.sh file under the directory /var/www/html/.
NAME=”website” #Name of the application (*)
DJANGODIR=/var/www/html/website/ # Django project directory (*)
SOCKFILE=/var/www/html/website/website.sock # we will communicate using this unix socket (*)
USER=ubuntu # the user to run as (*)
GROUP=www-data # the group to run as (*)
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn (*)
DJANGO_SETTINGS_MODULE=website.settings # which settings file should Django use (*)
DJANGO_WSGI_MODULE=website.wsgi # WSGI module name (*)
# Activate the virtual environment
cd $DJANGODIR
source /var/www/html/venv/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn’t exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use — daemon)
exec /var/www/html/website/venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
— name $NAME \
— workers $NUM_WORKERS \
— user $USER \
— bind=unix:$SOCKFILE
After this, we need to enable and start gunicorn as a service using the following commands.
sudo systemctl enable gunicorn.service
sudo systemctl start gunicorn.service
Installing Nginx
Time to set up Nginx as a server for our application and its static files.
- Install and start Nginx
sudo apt-get install nginx
sudo service nginx start
Each Nginx virtual server should be described by a file in the /etc/nginx/sites-available directory. You select which sites you want to enable by making symbolic links to those in the /etc/nginx/sites-enabled directory.
Now, to check if nginx was installed properly, we would need to configure nginx so that our server is connected to the internet. For a basic setup, we can follow the basic steps.
sudo nano /etc/nginx/sites-available/default
In the configuration file, there is a parameter within server, server_name. We need to put the IP address of our cloud server there, and easily check if the server is connected or not!
server {
listen 80;
server_name <server_ip>;
…
…
}
After this, run the following command.
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled
Then we will restart our nginx server.
sudo systemctl restart nginx
As we said before, nginx will be reverse proxying the gunicorn application server through the .sock file in the project root. This can be done by setting the location parameter within the nginx script. A basic demo nginx configuration:
server {
listen 80;
server_name <server_ip>;
location /static/ {
autoindex on;
alias /var/www/html/static/;
expires 1M;
access_log off;
add_header Cache-Control “public”;
proxy_ignore_headers “Set-Cookie”;
}
location / {
include proxy_params;
Proxy_pass http://unix:/var/www/html/<project_root>/<project_root_socket_gunicorn>.sock;
}
}
Now your nginx is ready to serve requests and it will forward it to your application but for this make sure you have a gunicorn server running.
Go to your browser and type <ec2-instance-dns> this will send a request to nginx and then it will forward that request to your server running with gunicorn.
Now, after we restart gunicorn and nginx, and provided that we have set up our project appropriately (setting up environment variables, adding the server IP address in ALLOWED_HOST etc.) we will be able to visit our django powered website using our server IP address!
Troubleshooting Nginx
The primary place to look for more information is in Nginx’s error logs. Generally, this will tell you what conditions caused problems during the proxying event. Follow the Nginx error logs by typing:
sudo tail -F /var/log/nginx/error.log
Personally, difficulties i faced during deployment was roots most of the times. So write the roots perfectly during deployment.
(inspired by