Deploy Django app with Nginx, Gunicorn, PostgreSQL & Supervisor in Linux— 2021
Currently we have latest deployment steps using docker or CI or CD tools. Even though I am writing this blogs for those who are beginner and want to deploy manually.
Installation based on :
Python3 , Django, Supervisor, Gunicorn, Postgres , Nginx
- First start with the updating packages that are already available on server.
$ sudo apt-get update
$ sudo apt-get upgrade
2. Install python3 and basic system dependencies
$ sudo apt install python-is-python3$ sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx python3.8-venv supervisor
3. PostgreSQL setup ( Optional )
$ sudo -u postgres psqlCREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;\q-------If you want to Change postgres user password:ALTER USER postgres PASSWORD 'myPassword';
4. Create environment and and install the requirements using requirements.txt
python -m venv envsource env/bin/activatepip install -r requirements.txt install below libs if not add in requirements.txt
- pip install psycopg2
- pip install gunicorn
5. Changes in the settings.py
ALLOWED_HOSTS = ['<your server's IP or domain name>']...
...DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'django_db',
'USER': 'db_user',
'PASSWORD': '<password you entered when creating db_user>',
'HOST': 'localhost',
'PORT': '5432', # Set to empty string for default.
}
}
6. Now you have gunicorn working, test it by running
gunicorn myproject.wsgi:application --bind 0.0.0.0:8001
7. If it works,
Let make it more configure. Create bash file and paste below code.
#!/bin/bash
NAME="myproject" # Name of the application
DJANGODIR=/home/ubuntu/myproject # Django project directory
SOCKFILE=/home/ubuntu/run/gunicorn.sock # communicate through unix socket
USER=ubuntu # the user to run as
GROUP=ubuntu # the group to run as
NUM_WORKERS=3 # processes Gunicorn spawn
DJANGO_SETTINGS_MODULE=myproject.settings # which settings file should Django use
DJANGO_WSGI_MODULE=myproject.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source /home/ubuntu/env/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 gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-
Now make this script executable.
$ sudo chmod u+x gunicorn_start.bash
8. To supervise any program through supervisor, you need to create configuration file. Create file — /etc/supervisor/conf.d/myproject.conf
Copy below content and paste it on above created file ( myproject.conf )
[program: myproject]
command = /home/ubuntu/gunicorn_start.bash
user = ubuntu
stdout_logfile = /home/ubuntu/logs/gunicorn_supervisor.log
redirect_stderr = true
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8
9. Create log file
mkdir -p /home/ubuntu/logs/
touch /home/ubuntu/logs/gunicorn_supervisor.log
10. Now for supervisor we should reread configuration files and update it so the our newly configuration file get add.
$ sudo supervisorctl reread$ sudo supervisorctl update# For Ubuntu 16.04 + :$ sudo systemctl restart supervisor$ sudo systemctl enable supervisor# For all services$ sudo supervisorctl status all$ sudo supervisorctl start all $ sudo supervisorctl stop all$ sudo supervisorctl restart all
11. For Nginx configuration:
create nginx configuration file for our application inside /etc/nginx/sites-available/ directory. create file with .conf extension.
upstream my_project_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/home/ubuntu/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name <your domain name>;
client_max_body_size 4G;
access_log /home/ubuntu/logs/nginx-access.log;
error_log /home/ubuntu/logs/nginx-error.log;
location /static/ {
alias /home/ubuntu/myproject/static/;
}
location /media/ {
alias /home/ubuntu/myproject/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://sample_project_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/ubuntu/myproject/static/;
}
}
12. After this we will need to create symbolic link for it, in the /etc/nginx/sites-enabled directory.
sudo ln -s /etc/nginx/sites-available/myproject.conf /etc/nginx/sites-enabled/myproject.conf
13. Now, start the Nginx.
$ sudo service nginx startor$ sudo /etc/init.d/nginx restart