Saturday, March 23, 2019

Install of Djnago (Nginx, uWSGI, Python3)

Prerequisites

Install Nginx

Add the following repository:
$ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
Then install nginx.
$ sudo yum update
$ sudo yum install -y nginx
Start and enable nginx.
$ sudo systemctl start nginx
$ sudo systemctl enable nginx

Install Python3

Enable IUS repository:
$ sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm
Install Python3.6 modules:
$ sudo yum install -y python36u python36u-libs python36u-devel python36u-pip python-pip gcc
To check if Python 3.6 is successfully installed, do the following commands:
$ sudo python3.6 -V
$ sudo which python3.6

SELinux

SELinux interrupts Apache for security reasons. I think it is better to disable SELinux permanently in the development environment.
$ sudo setenforce 0
And open the "/etc/selinux/config" file and set the SELinux to disabled:
$ sudo vi /etc/selinux/config
And change it like this:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.

SELINUX=disabled #Change HERE!!!!!

# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

Use venv of Python3

Go to your directory and use the venv:
$ cd /vagrant
$ python3.6 -m venv django-test
$ cd ./django-test
$ source bin/activate
And you will have a separated environment of your Python. In the virtual environment, you can use different version of Python and modules from the ones in the host machine.
Please note that you can exit the virtual environment as follows (but don't exit yet):
$ deactivate
Upgrade your pip of python3 just in case:
$ python3.6 -m pip install --upgrade pip

Install Django

Install Django as follows:
$ cd /vagrant/django-test
$ python3.6 -m pip install Django
$ django-admin.py startproject mysite
$ cd mysite

Add allowed host

Add "192.168.33.10" to "Allowed_Hosts" in the following file:
$ sudo vi /vagrant/django-test/mysite/mysite/settings.py
Change the allowed hosts as follows:

How to use vi editor is here:
Press a on your keyboard to be insert mode and you can edit the file. Press escape key to stop the insert mode. After stopping the insert mode, press Shift + g to go to the lowest row. :wq or Shift + zz to save and close the file. You can go to command mode by pressing : on your keyboard. To exit the file without saving the file, input :q! and enter. To search a word, press ? then write a word what you want to search. For example, if you write ?aaa and press enter, "aaa" is searched and highlighted in the file. Press n to jump to next match.)
Check if Django properly works by its built-in server:
$ cd /vagrant/django-test/mysite
$ python3.6 manage.py runserver 0.0.0:8000
And you should see django's install success message on this URL: http://192.168.33.10:8000/
Stop the built-in server by pressing CTRL + c once you check the install worked successfully.

Install uWSGI

Install uwsgi:
$ cd /vagrant/django-test/mysite
$ python3.6 -m pip install uwsgi
Check the version:
$ uwsgi --version
2.0.18

Hello World

views.py

Add a top-level module as follows:
$ cd /vagrant/django-test/mysite
$ python3.6 manage.py startapp mywebsite
Then open the 'views.py':
$ sudo vi /vagrant/django-test/mysite/mywebsite/views.py
and write as follows:
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world Django!!!!")

urls.py (mywebsite)

Now create a file named as urls.py:
$ sudo vi /vagrant/django-test/mysite/mywebsite/urls.py
Then write as follows inside so that it will call index function from views.py when accessed the root path:
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

urls.py (mysite)

Change urls.py file of mysite too.
$ sudo vi /vagrant/django-test/mysite/mysite/urls.py
Change it as follows. Make sure you import include from django.urls:
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('mywebsite/', include('mywebsite.urls')),
    path('admin/', admin.site.urls),
]

Check if it works

Check if Django properly works by its built-in server:
$ cd /vagrant/django-test/mysite
$ python3.6 manage.py runserver 0.0.0:8000
Go to http://192.168.33.10:8000/mywebsite/ and you will see the message you defined in index function.

Check if uWSGI can connect to Django

Check if uWSGI can connect to Django by the following command:
$ cd /vagrant/django-test/mysite/mysite
$ uwsgi --http :8000 --module mysite.wsgi
Go to http://192.168.33.10:8000/mywebsite/ and you will see the message you defined in index function.

Use Nginx and uWSGI together

Create mysite_nginx.conf:
$ sudo vi /vagrant/django-test/mysite/mysite/mysite_nginx.conf
And write as follows and save it:
# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/sockfile.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name 192.168.33.10; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /vagrant/django-test/mysite/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /vagrant/django-test/mysite/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
    }
}
Create a symlink so that Nginx can see the conf:
$ sudo ln -s /vagrant/django-test/mysite/mysite/mysite_nginx.conf /etc/nginx/conf.d/
Restart Nginx:
$ sudo systemctl restart nginx
Start uWSGI:
$ cd /vagrant/django-test/mysite/mysite
$ uwsgi --socket :8001 --module mysite.wsgi
You can see your django app is working on http://192.168.33.10:8000/mywebsite/ without the build-in server because it is using Nginx now. Stop the uWSGI by pressing CTRL+c.

Deploying static files

Open the following file:
$ sudo vi /vagrant/django-test/mysite/mysite/settings.py
Add the following:
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
as follows:

And run:
$ cd /vagrant/django-test/mysite/mysite
$ python3.6 manage.py collectstatic

Use Unix sockets instead of ports

Edit mysite_nginx.conf and change the upstream django:
upstream django {
    server unix:/var/run/mysite.sock; # for a file socket
    # server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
Restart Nginx:
$ sudo systemctl restart nginx
Run uWSGI:
$ sudo /vagrant/django-test/bin/uwsgi --socket /var/run/mysite.sock --module mysite.wsgi --chmod-socket=666

You can deamonize the uwsgi:
$ sudo /vagrant/django-test/bin/uwsgi --socket /var/run/mysite.sock --module mysite.wsgi --chmod-socket=666 --daemonize /var/log/uwsgi.log
To check nginx error log:
$ sudo less /var/log/nginx/error.log

Note

  • You can not put the socket file in /tmp directory because the files in /tmp might not be seen by Nginx. (/tmp can cause no such file or directory error.)

References