How to deploy a Django application:

How about greetings everyone, this is my first article in <» DesdeLinux (of several that I have in my drafts xD), I hope it is useful to you 😀

Well, in my new and current job, at the moment the migration of several systems to Django is being carried out (how strange eh ?? xD) and one of my tasks, apart from development, is putting these into production, so how good apprentice, since it was my first time putting an application into production on a real server: $ I started to read the official doc of each of the required packages of the stack (Gunicorn and Supervisord most of all), and seeing that the tutorials In Spanish they were not very clear to me in some aspects, I decided to create a mini guide with the steps that I followed to put the application into production, based on the Django, Gunicorn, Supervisord, Nginx and Postgresql stack.

In the case where I work, the servers still run on Debian Squeeze, but the guide should be fully valid for other distributions ... so let's get straight to the point and get started:

I will work as a super user. First of all, the following packages are required:

PIP -> Tool to install and manage packages for Python
aptitude install python-pip

Nginx -> Web server (we will use it as a reverse proxy and to cache the static files 'img, js, css') We install it with:
aptitude install nginx

Supervisor -> Application to manage and monitor our application, although it is used for much more. We install it with:
aptitude install supervisor

Virtualenv -> It helps us to create a customized virtual execution environment for our application. We install it with:
aptitude install python-virtualenv

gunicorn -> web server for python (we won't install this yet)

I assume they should already have postgresql installed and configured

psychopg2 -> Postgresql connector for python (we won't install it yet either)

Create virtual environment with virtualenv:

First we are going to move to the working directory that we will use for putting into production:
cd /var/www/

Then in this directory we will create the virtual environment:
virtualenv ENV-nombreApp

We move to the directory that I just created virtualenv
cd ENV-nombreAPP

We copy the application in this directory and now we proceed to activate the environment with:
source bin/activate

The prompt should now look like (ENV)usuario@host:

This will now make everything we do is stored in the directory / var / www / ENV-appname / without affecting system packages

Now we move to the application directory:
cd nombreApp

We proceed to install the list of application dependencies (if necessary), in which they are specified in the file requirements.txt:
pip install -r requirements.txt

We can also install packages individually, for example, to install the connector of postgresql:
pip install psycopg2

GUnicorn installation and configuration:

To install it we do it in the same way:
pip install gunicorn

Now we are going to configure it, for this we are going to create a file called gunicorn-deploy.py in the root of our application, (although the name can be anything) with the following content:

bind = "127.0.0.1:8001" # dirección a donde accederá Nginx
logfile = "/var/www/logs/nombreApp/gunicorn.log" # dirección donde estarán los logs de la aplicación
workers = 1 # dependerá en medida de la carga de trabajo que tenga la aplicación, también depende del hardware con que se cuente
loglevel = 'info' # tipo de logging

Supervisord configuration:

Now let's set the supervisor, for that we generate the configuration file with

echo_supervisord_conf > /etc/supervisord.conf

Now we edit the configuration file:
vim /etc/supervisord.conf

And we uncomment the following lines by removing the; (semicolon):

[unix_http_server] file = / tmp / supervisor.sock [supervisord] logfile = / var / log / supervisord.log logfile_maxbytes = 50MB logfile_backups = 10 loglevel = debug pidfile = / var / run / supervisord.pid nodaemon = false minfds = 1024 minprocs = 200 [rpcinterface: supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface: make_main_rpcinterface [supervisorctl] serverurl = unix: [program: appname] command = / var / www / ENV-appname / bin / django_unicorn -c / var / www / ENV -Appname / appname / gunicorn-deploy.py directory = / var / www / ENV-appname / appname / autostart = true autorestart = true user = Username redirect_stderr = true stdout_logfile = / var / www / logs / appname / supervisord.log

Now we will create the script for supervisord to start with the system, for that we will create the file:
vim /etc/init.d/supervisord

And we add the following content:

 # Supervisord auto-start # # description: Auto-starts supervisord # processname: supervisord # pidfile: /var/run/supervisord.pid SUPERVISORD = / usr / local / bin / supervisord SUPERVISORCTL = / usr / local / bin / supervisorctl case $ 1 in start) echo -n "Starting supervisord:" $ SUPERVISORD echo ;; stop) echo -n "Stopping supervisord:" $ SUPERVISORCTL shutdown echo ;; restart) echo -n "Stopping supervisord:" $ SUPERVISORCTL shutdown echo echo -n "Starting supervisord:" $ SUPERVISORD echo ;; that C

And now we give execute permissions to the file so that it can start with the system:
sudo chmod +x /etc/init.d/supervisord

We update the links to start the service:
sudo update-rc.d supervisord defaults

We start the service:
sudo /etc/init.d/supervisord start

Setting up nginx:

This step is also quite simple, we will create the following configuration file of for our application:

vim /etc/nginx/sites-enabled/nombreApp

And we will add the following content to you

server {listen 9001; # port where they want nginx server_name to listen www.domain.com; # or 192.168.0.100, address that we will access access_log /var/log/nginx/Appname.access.log; # where we will have the application log location / {# where nginx will call when accessing www.dominio.com/ proxy_pass http://127.0.0.1:8001; proxy_set_header Host $ http_host; } location / static / {# where nginx will access when we enter www.domain.com/static/ alias / var / www / ENV-appname / appname / staticfiles /; }}

And we restart nginx:
service nginx restart

Setting up Django:

Let's modify the django configuration file:
vim nombreApp/settings.py

We look for the line that says DEBUG=True and we change the valueremaining DEBUG=False

We add the DB parameters:

DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql_psycopg2', # or mysql, or whatever 'NAME': 'DBName', 'USER': 'DBUser', 'PASSWORD' are using : 'password DB', 'HOST': 'localhost', # or the one they need 'PORT': '', # or the one they are using}}

We look for the line ALLOWED_HOSTS = [] and we add the domain or the address through which we will access, leaving something like ALLOWED_HOSTS = ['www.domain.com']

We configure the directory for the static files, we look for the line that says STATIC_ROOT = ' ' and we change the value, placing the absolute path where we want our static files to be, in my case I left it more or less like this STATIC_ROOT='/var/www/ENV-nombreApp/nombreApp/statics/'

Almost finished, we execute the following command:
./manage.py collectstatic

This will create a folder with the name 'static in the path that we specify in the settings.py ', that's where all our static files will be.

And finally we restart the supervisor to take the new changes:
supervisorctl restart nombreApp

And that would be all, in the end it was not so much true? it seemed simple to me 😀

I hope it is useful to you, greetings 😉

GUnicorn documentation

Supervisord documentation


Leave a Comment

Your email address will not be published. Required fields are marked with *

*

*

  1. Responsible for the data: Miguel Ángel Gatón
  2. Purpose of the data: Control SPAM, comment management.
  3. Legitimation: Your consent
  4. Communication of the data: The data will not be communicated to third parties except by legal obligation.
  5. Data storage: Database hosted by Occentus Networks (EU)
  6. Rights: At any time you can limit, recover and delete your information.

  1.   f3niX said

    I understand that the Django app should not be placed in the root of the web server folder (/ var / www)? For security, I don't know if I'm wrong.

    Greetings.

    1.    urKh said

      All right !!! It was something that I was totally unaware of, I will update the entry 😛 and as soon as I return on Monday I will make changes in the xD application
      Thank you

  2.   Rodrigo Bravo (goidor) said

    Epale brother good tutorial. Recently I was also in the same but in Debian 7, I had to search and read more or less. I recommend that you create the virtual environment of virtualenv in the user's home in a hidden folder.

    Regards!

  3.   serv fenriz said

    hahaha ctm I yesterday documenting Django and you are already going through the galaxy 999999 Greetings men xD

  4.   daniel2ac said

    Very good article =) just a week ago I deployed my django app but I did it with uwsgi and nginx, do you know what advantage gunicorn has? I've seen it mentioned a lot.
    It's nice to see that django is becoming very popular, the truth is the best framework I've seen =)

  5.   ozkar said

    For the STATIC_ROOT what I do is define a global variable. Something like this:

    import os
    PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
    STATIC_ROOT = os.path.join(PROJECT_PATH, '../backend/static')

    Where backend is an app that I created. This way I make sure that where I deploy the project, the global path is the same.

  6.   sgmart said

    Interesting, I will try in the future.

    By the way, does anyone know how to enable accents and non-ascii characters in a django application?

    I've looked everywhere, none of the following methods work for me:
    sys.setdefaultencoding ('utf-8') # in sites.py

    # - * - coding: utf-8 - * - # in every python file

    Editing site.py, and putting utf-8 instead of ascii is supposed to work, but $ file models.py informs me that my file is still an ascii.

    Any Suggestions?

    1.    sgmart said

      It worked!!!!

  7.   anime230 said

    very good tutorial but you could do one of how to upload my app on a web server already in production
    Thank you