Django is a python framework for creating powerful web applications. Here i’m going to be talking about deploying a django application to a VPS ( virtual private server).

Before diving in let me wrap a few thing about django. This is for newbies performing the deploy for first time. If you are in the club already please skip this section.

I’m sure you have used this command to build the application on your local machine.

python manage.py runserver

This one command did everything for you so far, but to deploy the application to production there is a few more steps, ill explain the basic ones and why its done, then proceed to deployment process.

  • Accessing DJango : In production you have used port 8000 or 127.0.0.1:8000 to access the django but you can’t do that on a web production, to solve the port issue a web-server is used to proxy request to django.
  • File Locations : You had your files inside the django project directory and it worked well, but for production you cannot, and django will not be serving static files like image, CSS, javascript etc. They are going to be handled by a web server like Nginx or via a CDN. Read more on Serving Files in Django.
  • System & other Configs: Other than the database username and password, you have to configure file paths for static files, media files and other settings. Read more on Local Setting in django and how to work with them.
  • Demon : There’s no one on the server to run manage.py runserver it and keep the terminal opened, this has to be running to keep the django server running. We will assign this task to Guicorn to bind the request to django.

These are the basic settings on a typical django application to get it ready for production, more steps will be added based on your application and plugins you gonna be using.

Pre Server Config

I won’t focus more on server setup, but ill explain a few steps needed to get django running. I’m using a machine with ubuntu 16.04.1 LTS on ovh. Refer web hosting review to choose a good one for your need.

We will deploy Django application to a Ubuntu Machine with

  • Nginx : Serve files and proxy the incoming request.
  • PostgreSQL: Database
  • Guicorn: Deploy Django

Init

Lets get in, SSH into your box and upgrade the packed in your package manager, its good to make sure the packages are up-to-date.

sudo apt-get update
sudo apt-get upgrade

Database

Lets get some data items configured, i’m using PostgreSQL, you can use any other database like mysql, mongodb etc. In that case refer the documentation and do the similar setup to get database ready.

sudo apt-get install libpq-dev python-dev
sudo apt-get install postgresql postgresql-contrib

That concludes the installation, we need a database and user account for django. To create a database with PostgreSQL start by running the following command:


sudo su - postgres
createdb 
createuser -P 
# You will be prompted to enter a password for the user, and to confirm it. 

# Now activate the PostgreSQL command line interface
psql

#grand privilege or according to your need.
GRANT ALL PRIVILEGES ON DATABASE  TO ;

Use q to quit the psql and exit to exit postgres.

Web Server

Web server takes the incoming request and proxies to Django, and also servers static and media files. I’m using NGINX. If this is not the case, refer documentation for your web server of choice and complete the step.

sudo apt-get install nginx

Now you will be able to see NGINX welcome page if you try to access your serve IP address.

Setup configuration file for your project, NGINX can server multiple applications and each application can have a separate configurations. To get started you can clone the default configuration files in the NGINX /etc/nginx/sites-available/default or make a new files inside the directory /etc/nginx/sites-available/.

Here’s what the file is going to do :

  • Set the pubic location for static and media files as they are going to be served from NGINX directly without intervention of django in any form.
  • Set up proxy to transfer request to django.

server {
    server_name yourdomain_or_ip.com;
    # Nginx will execute the setting only for this 

    access_log off;
    # no one logs on production 

   # Static files
    location /static/ {
        alias /var/www/packman/static/;
    }

    # Media files 0r User uploaded files
    location /media/ {
        alias /var/www/packman/media/;
    }

   # Proxy request
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Now we need to set up a symbolic link in the /etc/nginx/sites-enabled directory that points to this configuration file to inform NGINX to use this config file.

To create a symblink navigate to /etc/nginx/sites-enabled and type the following

ln -s ../sites-available/

Restart NGINX to take these changes to action.

service nginx restart

Virtualenv

If you don’t know virtualenv, it’s a tool to create isolated Python environments. If you haven’t used this i recommend you go ahead and do some research on virtualenv and migrate your project.

Virtualenv is not required to run use django, if you want to go ahead without it skip this section and proceed. But its highly recommended to use virtualenv to keep your application packages in an isolated environment from the system.

sudo apt-get install python-virtualenv

Navigate to a location in vps where you want your django project to live, it need not in the public directory of NGINX or web server. Now setup virtualenv and activate it.

# create virtual env
virtualenv venv
#venv is the name of virtualenv i'm going to use

#activate venv
source venv/bin/activate

Now you should see virtualenv name infront of your terminal in parenthesis, that means you are inside venv.

(venv) root@vps104319:~/packman/packman-evc#

any installations done using pip will be local to this environment and won't interfere with the packages in the system, this allows replicating the environment for your django or python app easy.

To exit from the virtualenv type in deactivate. Don't do it, next operations need to be in the virtualenv ( if you are using it ).

Clone the Code

If you haven't changed the directory from the virtualenv installation, clone the code where you are, else navigate to the directory where you setup your virtualenv and clone the code.

Once cloned ensure your virtualenv is active and proceed installing the packages for the application.

Configure the settings for database, static and media files, any other depending on your application.

It's time to test the configurations, execute manage.py migrate to migrate the database, you will see a similar execution of migration as you would on your machine.

Collect the static files to NGINX public directory so they can be served by NGINX, manage.py collectstatic completes that for you if you have configured it correctly. Refer static and media files to know how to do that.

Now you can use manage.py runserver 0.0.0.0:8000 to run the server and to access it via server IP, if it works you are just a step away from completion. Quit the server using cmd-c or control-c.

Guicorn

Guicon will keep the django running and binds the request to port 8000. To install Guicon, activate virtualenv then execute the following:

pip install gunicorn

Navigate to your app's root directory, its the directory where manage.py exist and execute the following to bind guicorn.

gunicorn .wsgi 0.0.0.0:8000 --daemon --workers=3

guicorn is run using wsgi, and 0.0.0.0:8000 is the ip address and port django is bound to.

--daemon --workers=3 is the number of workers to be started for guicorn, Gunicorn is based on the pre-fork worker model refer docs for more info http://docs.gunicorn.org/en/stable/design.html.

No of workers to be used depends on the server and application requirements but a formula used in the community to gauge how many workers would be suitable is :

NUM_WORKERS = 1 + ( 2 * NUM_CORES) 

And that's it! You've now got your app deployed to production and ready to go.