Original post – https://www.codingpaths.com/django/deploy-django/
Deploy Django
In this blog, we will learn how to deploy Django Application with uWSGI and nginx on CentOS’7. Django is the most popular python based backend framework with the aim of rapid web development. Before installing anything, I recommend to read my previous post where I have discussed about initial server setup with ssh keys.
1. Installing the prerequisites
Installing python3.6
First install the latest packages from EPEL and RPM. EPEL(Extra Packages for Enterprise Linux) is an open source repository that contains the latest packages for Red Hat Linux distributions. RPM is also an open source package management system from Red Hat. After all this, lets install python3 –
<span>sudo </span>yum <span>install</span> <span>-y</span> epel-release<span>sudo </span>yum <span>install</span> <span>-y</span> https://centos7.iuscommunity.org/ius-release.rpm<span>sudo </span>yum update<span>sudo </span>yum <span>install</span> <span>-y</span> python36u python36u-libs python36u-devel python36u-pip python-devel<span>sudo </span>yum <span>install</span> <span>-y</span> epel-release <span>sudo </span>yum <span>install</span> <span>-y</span> https://centos7.iuscommunity.org/ius-release.rpm <span>sudo </span>yum update <span>sudo </span>yum <span>install</span> <span>-y</span> python36u python36u-libs python36u-devel python36u-pip python-develsudo yum install -y epel-release sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm sudo yum update sudo yum install -y python36u python36u-libs python36u-devel python36u-pip python-devel
Upgrading pip and installing virtualenv
Pip is the most popular python package installer. Virtual environments are used for separating the different versions of any package for different projects.
<span>sudo </span>pip3.6 <span>install</span> <span>--upgrade</span> pip<span>sudo </span>pip <span>install </span>virtualenv virtualenvwrapper<span>sudo </span>pip3.6 <span>install</span> <span>--upgrade</span> pip <span>sudo </span>pip <span>install </span>virtualenv virtualenvwrappersudo pip3.6 install --upgrade pip sudo pip install virtualenv virtualenvwrapper
Configuring the shell
We will use Env directory to hold all our virtual environments. This can be configured in .bashrc
file.
<span>echo</span> <span>"export WORKON_HOME=~/Env"</span> <span>>></span> ~/.bashrc<span>echo</span> <span>"source /usr/bin/virtualenvwrapper.sh"</span> <span>>></span> ~/.bashrc<span>echo</span> <span>"export WORKON_HOME=~/Env"</span> <span>>></span> ~/.bashrc <span>echo</span> <span>"source /usr/bin/virtualenvwrapper.sh"</span> <span>>></span> ~/.bashrcecho "export WORKON_HOME=~/Env" >> ~/.bashrc echo "source /usr/bin/virtualenvwrapper.sh" >> ~/.bashrc
Now, open /usr/bin/virtualenvwrapper.sh
with either vim or nano. Find the line –
VIRTUALENVWRAPPER_PYTHON="$(command \which python)"VIRTUALENVWRAPPER_PYTHON="$(command \which python)"VIRTUALENVWRAPPER_PYTHON="$(command \which python)"
and replace python with python3.6 as –
VIRTUALENVWRAPPER_PYTHON="$(command \which python3.6)"VIRTUALENVWRAPPER_PYTHON="$(command \which python3.6)"VIRTUALENVWRAPPER_PYTHON="$(command \which python3.6)"
Now, lets reflect these changes –
<span>source</span> ~/.bashrc<span>source</span> ~/.bashrcsource ~/.bashrc
2. Configuring Django project
Creating virtual environments
mkvirtualenv env_1mkvirtualenv env_1mkvirtualenv env_1
The environment env_1 gets automatically activated. The same can be verified by –
which pip<span># Output: ~/Env/env_1/bin/pip</span>which pip <span># Output: ~/Env/env_1/bin/pip</span>which pip # Output: ~/Env/env_1/bin/pip
Copying Django project from local to remote
Since, we have activated our virtual env, now we will copy our django project to remote server using scp. If you have uploaded it on github, just install git via yum and then git clone the project. But before doing this, lets grab all the requirements of the project. If your project already contains a requirements file, then you can skip this part. “cd” into your project’s directory and after activating virtual env in your local machine, use the following command to list out requirements in requirements.txt file in your local terminal-
pip freeze <span>></span> requirements.txtpip freeze <span>></span> requirements.txtpip freeze > requirements.txt
Now, to copy the project, use the following command in your local terminal. Do remember to put your ip and user_name configured in previous post. Write the complete path of your django project from root in local machine. This will copy the project in the home directory of the server.
scp <span>-r</span> /path/to/project user_name@your_ip_here:~scp <span>-r</span> /path/to/project user_name@your_ip_here:~scp -r /path/to/project user_name@your_ip_here:~
Now, connect to your server and activate the virtual env.
ssh user_name@your_ip_hereworkon env_1ssh user_name@your_ip_here workon env_1ssh user_name@your_ip_here workon env_1
Let’s install all the requirements for the project. Use the path to requirements.txt file.
pip <span>install</span> <span>-r</span> /path/to/requirements.txtpip <span>install</span> <span>-r</span> /path/to/requirements.txtpip install -r /path/to/requirements.txt
Installing MySQL from rpm
<span>sudo </span>rpm <span>-ivh</span> https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm<span>sudo </span>rpm <span>-ivh</span> https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpmsudo rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
Check if Mysql repo has been enabled –
<span>sudo </span>yum repolist all | <span>grep </span>mysql | <span>grep </span>enabled<span># Output : enabled</span><span>sudo </span>yum repolist all | <span>grep </span>mysql | <span>grep </span>enabled <span># Output : enabled</span>sudo yum repolist all | grep mysql | grep enabled # Output : enabled
Install and enable mysql –
<span>sudo </span>yum <span>-y</span> <span>install </span>mysql-community-server<span>sudo </span>systemctl start mysqld<span>sudo </span>systemctl <span>enable </span>mysqld<span>sudo </span>systemctl status mysqld<span>sudo </span>yum <span>-y</span> <span>install </span>mysql-community-server <span>sudo </span>systemctl start mysqld <span>sudo </span>systemctl <span>enable </span>mysqld <span>sudo </span>systemctl status mysqldsudo yum -y install mysql-community-server sudo systemctl start mysqld sudo systemctl enable mysqld sudo systemctl status mysqld
Copy the mysql temporary root password from the command given below and paste this while secure installation of mysql. Change the root password and hit Enter for default actions.
<span>cat</span> /var/log/mysqld.log | <span>grep</span> <span>-i</span> <span>'temporary password'</span>mysql_secure_installation<span>cat</span> /var/log/mysqld.log | <span>grep</span> <span>-i</span> <span>'temporary password'</span> mysql_secure_installationcat /var/log/mysqld.log | grep -i 'temporary password' mysql_secure_installation
We have successfully installed mysql and now, we need a database to run our project. First, open the mysql interface and enter the root password –
mysql <span>-u</span> root <span>-p</span>mysql <span>-u</span> root <span>-p</span>mysql -u root -p
Now, in mysql, create a database –
mysql> CREATE DATABASE first_db<span>;</span>mysql> SHOW DATABASES<span>;</span>mysql> <span>exit</span>mysql> CREATE DATABASE first_db<span>;</span> mysql> SHOW DATABASES<span>;</span> mysql> <span>exit</span>mysql> CREATE DATABASE first_db; mysql> SHOW DATABASES; mysql> exit
After this, we need to install a client to communicate with mysql –
<span>sudo </span>yum <span>install</span> <span>-y</span> mysql-connector-python.x86_64 mysql-community-devel.x86_64 mysql-cluster-community-client.x86_64 mysql-shell.x86_64 mysql-router.x86_64 gccpip <span>install </span>mysqlclient <span># inside the virtual environment</span><span>sudo </span>yum <span>install</span> <span>-y</span> mysql-connector-python.x86_64 mysql-community-devel.x86_64 mysql-cluster-community-client.x86_64 mysql-shell.x86_64 mysql-router.x86_64 gcc pip <span>install </span>mysqlclient <span># inside the virtual environment</span>sudo yum install -y mysql-connector-python.x86_64 mysql-community-devel.x86_64 mysql-cluster-community-client.x86_64 mysql-shell.x86_64 mysql-router.x86_64 gcc pip install mysqlclient # inside the virtual environment
Changing settings.py file
With everything installed, let’s change some settings for the project –
<span>sudo </span>nano ~/project_name/project_name/settings.py<span>sudo </span>nano ~/project_name/project_name/settings.pysudo nano ~/project_name/project_name/settings.py
Add the following line to the last of the file. As we will be using nginx to deploy the application, this line tells django to place our static files in ‘static’ directory. This helps nginx to easily serve these static files.
<span>STATIC_ROOT</span> <span>=</span> <span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>BASE_DIR</span><span>,</span> <span>"static/"</span><span>)</span><span>STATIC_ROOT</span> <span>=</span> <span>os</span><span>.</span><span>path</span><span>.</span><span>join</span><span>(</span><span>BASE_DIR</span><span>,</span> <span>"static/"</span><span>)</span>STATIC_ROOT = os.path.join(BASE_DIR, "static/")
Do not forget to change the default database configurations to –
<span>DATABASES</span> <span>=</span> <span>{</span><span>'default'</span><span>:</span> <span>{</span><span>'ENGINE'</span><span>:</span> <span>'django.db.backends.mysql'</span><span>,</span><span>'NAME'</span><span>:</span> <span>'first_db'</span><span>,</span><span>'USER'</span><span>:</span> <span>'root'</span><span>,</span><span>'PASSWORD'</span><span>:</span> <span>'your-root-password'</span><span>,</span><span>'HOST'</span><span>:</span> <span>'localhost'</span><span>,</span><span>'PORT'</span><span>:</span> <span>''</span><span>,</span><span>}</span><span>}</span><span>DATABASES</span> <span>=</span> <span>{</span> <span>'default'</span><span>:</span> <span>{</span> <span>'ENGINE'</span><span>:</span> <span>'django.db.backends.mysql'</span><span>,</span> <span>'NAME'</span><span>:</span> <span>'first_db'</span><span>,</span> <span>'USER'</span><span>:</span> <span>'root'</span><span>,</span> <span>'PASSWORD'</span><span>:</span> <span>'your-root-password'</span><span>,</span> <span>'HOST'</span><span>:</span> <span>'localhost'</span><span>,</span> <span>'PORT'</span><span>:</span> <span>''</span><span>,</span> <span>}</span> <span>}</span>DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'first_db', 'USER': 'root', 'PASSWORD': 'your-root-password', 'HOST': 'localhost', 'PORT': '', } }
And also add your ip in the allowed hosts –
<span>ALLOWED_HOSTS</span> <span>=</span> <span>[</span><span>'your_ip_here'</span><span>]</span><span>ALLOWED_HOSTS</span> <span>=</span> <span>[</span><span>'your_ip_here'</span><span>]</span>ALLOWED_HOSTS = ['your_ip_here']
Opening port 8000
<span>sudo </span>firewall-cmd <span>--permanent</span> <span>--add-service</span><span>=</span>http<span>sudo </span>firewall-cmd <span>--permanent</span> <span>--add-port</span><span>=</span>8000/tcp<span>sudo </span>firewall-cmd <span>--complete-reload</span><span>sudo </span>firewall-cmd <span>--list-all</span><span>sudo </span>firewall-cmd <span>--permanent</span> <span>--add-service</span><span>=</span>http <span>sudo </span>firewall-cmd <span>--permanent</span> <span>--add-port</span><span>=</span>8000/tcp <span>sudo </span>firewall-cmd <span>--complete-reload</span> <span>sudo </span>firewall-cmd <span>--list-all</span>sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-port=8000/tcp sudo firewall-cmd --complete-reload sudo firewall-cmd --list-all
Running the application
First, flush out the initial migrations and delete the sqlite database. “cd” into your project’s directory and use the following commands –
find <span>.</span> <span>-path</span> <span>"*/migrations/*.py"</span> <span>-not</span> <span>-name</span> <span>"__init__.py"</span> <span>-delete</span>find <span>.</span> <span>-path</span> <span>"*/migrations/*.pyc"</span> <span>-delete</span><span>rm</span> <span>-f</span> db.sqlite3find <span>.</span> <span>-path</span> <span>"*/migrations/*.py"</span> <span>-not</span> <span>-name</span> <span>"__init__.py"</span> <span>-delete</span> find <span>.</span> <span>-path</span> <span>"*/migrations/*.pyc"</span> <span>-delete</span> <span>rm</span> <span>-f</span> db.sqlite3find . -path "*/migrations/*.py" -not -name "__init__.py" -delete find . -path "*/migrations/*.pyc" -delete rm -f db.sqlite3
Run the migrations to sync up with database –
python manage.py collectstaticpython manage.py makemigrationspython manage.py migratepython manage.py collectstatic python manage.py makemigrations python manage.py migratepython manage.py collectstatic python manage.py makemigrations python manage.py migrate
So, finally we can run the server and see the application accessible globally –
python manage.py runserver 0.0.0.0:8000python manage.py runserver 0.0.0.0:8000python manage.py runserver 0.0.0.0:8000
Go to the web browser and enter your_ip:8000 to access the django application.
3. Setting up uWSGI and nginx
Configuring uWSGI globally
Store all the configuration files to /etc/uwsgi/sites. You should use your project name for all configurations –
<span>sudo </span>pip <span>install </span>uwsgi<span>sudo mkdir</span> <span>-p</span> /etc/uwsgi/sites<span>cd</span> /etc/uwsgi/sites<span>sudo </span>nano project_name.ini<span>sudo </span>pip <span>install </span>uwsgi <span>sudo mkdir</span> <span>-p</span> /etc/uwsgi/sites <span>cd</span> /etc/uwsgi/sites <span>sudo </span>nano project_name.inisudo pip install uwsgi sudo mkdir -p /etc/uwsgi/sites cd /etc/uwsgi/sites sudo nano project_name.ini
Add the following lines to the .ini file. Do remember to use your project and user name.
<span>[</span>uwsgi]project <span>=</span> project_nameusername <span>=</span> user_namebase <span>=</span> /home/%<span>(</span>username<span>)</span>chdir <span>=</span> %<span>(</span>base<span>)</span>/%<span>(</span>project<span>)</span>home <span>=</span> %<span>(</span>base<span>)</span>/Env/env_1module <span>=</span> %<span>(</span>project<span>)</span>.wsgi:applicationmaster <span>=</span> <span>true </span>processes <span>=</span> 5uid <span>=</span> %<span>(</span>username<span>)</span>socket <span>=</span> /run/uwsgi/%<span>(</span>project<span>)</span>.sockchown-socket <span>=</span> %<span>(</span>username<span>)</span>:nginxchmod-socket <span>=</span> 660vacuum <span>=</span> <span>true</span><span>[</span>uwsgi] project <span>=</span> project_name username <span>=</span> user_name base <span>=</span> /home/%<span>(</span>username<span>)</span> chdir <span>=</span> %<span>(</span>base<span>)</span>/%<span>(</span>project<span>)</span> home <span>=</span> %<span>(</span>base<span>)</span>/Env/env_1 module <span>=</span> %<span>(</span>project<span>)</span>.wsgi:application master <span>=</span> <span>true </span>processes <span>=</span> 5 uid <span>=</span> %<span>(</span>username<span>)</span> socket <span>=</span> /run/uwsgi/%<span>(</span>project<span>)</span>.sock chown-socket <span>=</span> %<span>(</span>username<span>)</span>:nginx chmod-socket <span>=</span> 660 vacuum <span>=</span> <span>true</span>[uwsgi] project = project_name username = user_name base = /home/%(username) chdir = %(base)/%(project) home = %(base)/Env/env_1 module = %(project).wsgi:application master = true processes = 5 uid = %(username) socket = /run/uwsgi/%(project).sock chown-socket = %(username):nginx chmod-socket = 660 vacuum = true
Ctrl+x to exit and press y to save the changes. Base and home contain the full path for the home directory and virtual environment respectively. We have created a master process for loading our app server. Here, we have used Unix Socket. This socket uses uWSGI protocol which helps nginx to reverse proxy.
<span>sudo </span>nano /etc/systemd/system/uwsgi.service<span>sudo </span>nano /etc/systemd/system/uwsgi.servicesudo nano /etc/systemd/system/uwsgi.service
Add the following lines. Do remember to use your user name in ExecStartPre of Service section.
<span>[</span>Unit]<span>Description</span><span>=</span>uWSGI Emperor service<span>[</span>Service]<span>ExecStartPre</span><span>=</span>/usr/bin/bash <span>-c</span> <span>'mkdir -p /run/uwsgi; chown user_name:nginx /run/uwsgi'</span><span>ExecStart</span><span>=</span>/usr/bin/uwsgi <span>--emperor</span> /etc/uwsgi/sites<span>Restart</span><span>=</span>always<span>KillSignal</span><span>=</span>SIGQUIT<span>Type</span><span>=</span>notify<span>NotifyAccess</span><span>=</span>all<span>[</span>Install]<span>WantedBy</span><span>=</span>multi-user.target<span>[</span>Unit] <span>Description</span><span>=</span>uWSGI Emperor service <span>[</span>Service] <span>ExecStartPre</span><span>=</span>/usr/bin/bash <span>-c</span> <span>'mkdir -p /run/uwsgi; chown user_name:nginx /run/uwsgi'</span> <span>ExecStart</span><span>=</span>/usr/bin/uwsgi <span>--emperor</span> /etc/uwsgi/sites <span>Restart</span><span>=</span>always <span>KillSignal</span><span>=</span>SIGQUIT <span>Type</span><span>=</span>notify <span>NotifyAccess</span><span>=</span>all <span>[</span>Install] <span>WantedBy</span><span>=</span>multi-user.target[Unit] Description=uWSGI Emperor service [Service] ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown user_name:nginx /run/uwsgi' ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/sites Restart=always KillSignal=SIGQUIT Type=notify NotifyAccess=all [Install] WantedBy=multi-user.target
[Unit] section describes our service. [Service] section manages various applications. [Install] section ties up multi-user system state.
Configuring Nginx
Installing Nginx –
<span>sudo </span>yum <span>-y</span> <span>install </span>nginx<span>sudo </span>nano /etc/nginx/nginx.conf<span>sudo </span>yum <span>-y</span> <span>install </span>nginx <span>sudo </span>nano /etc/nginx/nginx.confsudo yum -y install nginx sudo nano /etc/nginx/nginx.conf
Add the following lines. Do remember to use your user name and project name in root and uwsgi_pass.
server <span>{</span>listen 8000<span>;</span>server_name localhost<span>;</span>location <span>=</span> favicon.ico <span>{</span> access_log off<span>;</span> log_not_found off<span>;</span> <span>}</span>location /static/ <span>{</span>root /home/user_name/project_name<span>;</span><span>}</span>location / <span>{</span>include uwsgi_params<span>;</span>uwsgi_pass unix:/run/uwsgi/project_name.sock<span>;</span><span>}</span><span>}</span>server <span>{</span> listen 8000<span>;</span> server_name localhost<span>;</span> location <span>=</span> favicon.ico <span>{</span> access_log off<span>;</span> log_not_found off<span>;</span> <span>}</span> location /static/ <span>{</span> root /home/user_name/project_name<span>;</span> <span>}</span> location / <span>{</span> include uwsgi_params<span>;</span> uwsgi_pass unix:/run/uwsgi/project_name.sock<span>;</span> <span>}</span> <span>}</span>server { listen 8000; server_name localhost; location = favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/user_name/project_name; } location / { include uwsgi_params; uwsgi_pass unix:/run/uwsgi/project_name.sock; } }
Above, we have set up a server block, with an open port to listen from. We have also specified the static file location and passed all the traffic to unix socket. Make sure the syntax of nginx file is correct and change permissions of the user.
<span>sudo </span>nginx <span>-t</span><span>sudo </span>usermod <span>-a</span> <span>-G</span> user_name nginx<span>chmod </span>710 /home/user_name<span>sudo </span>nginx <span>-t</span> <span>sudo </span>usermod <span>-a</span> <span>-G</span> user_name nginx <span>chmod </span>710 /home/user_namesudo nginx -t sudo usermod -a -G user_name nginx chmod 710 /home/user_name
Start and enable the nginx and uwsgi.
<span>sudo </span>systemctl start nginx<span>sudo </span>systemctl start uwsgi<span>sudo </span>systemctl <span>enable </span>nginx<span>sudo </span>systemctl <span>enable </span>uwsgi<span>sudo </span>systemctl start nginx <span>sudo </span>systemctl start uwsgi <span>sudo </span>systemctl <span>enable </span>nginx <span>sudo </span>systemctl <span>enable </span>uwsgisudo systemctl start nginx sudo systemctl start uwsgi sudo systemctl enable nginx sudo systemctl enable uwsgi
Now you can directly access the django application from the ip with an open port.
Thanks for reading!
原文链接:Deploy Django
暂无评论内容