de Sumeet Kumar

Cum se creează un server Django care rulează uWSGI, NGINX și PostgreSQL pe AWS EC2 cu Python 3.6

Cum se creeaza un server Django care ruleaza uWSGI NGINX

Punerea în funcțiune a unui server pentru un nou proiect de fiecare dată ar putea fi consumatoare de timp sau dificilă pentru noii dezvoltatori. Așa că m-am gândit să scriu un ghid pas cu pas care să ușureze procesul de implementare.

Dacă nu aveți chef să citiți, puteți copia lipiți fiecare pas așa cum este descris (înlocuiți valorile) și puteți pune serverul în funcțiune?

Condiții preliminare:

  1. Instanța Amazon Linux EC2 funcționează cu perechea de chei asociată (accesul la acesta).
  2. Portul 22, 80 trebuie să fie deschis pentru această instanță.
  3. Aplicația Django pe care doriți să o implementați.
  4. Setările bazei de date sunt configurate pentru a utiliza PostgreSQL.
  5. requirements.txt este prezent în aplicația dvs., având lista de dependențe de instalat.
  6. Depozit Git pentru aplicația dvs. Django.

SSH și actualizați instanța Ubuntu

Trebuie să vă conectați la instanța dvs. EC2, deci asigurați-vă că aveți portul 22 deschideți pentru instanța dvs. și apoi efectuați o actualizare / actualizare.

ssh -i path-to-your-key.pem ubuntu@your-aws-instance-public-ip

sudo apt-get update && sudo apt-get upgrade -y

Instalarea Python3.6.x pe AWS EC2 (Ubuntu 16.04)

Vom descărca fișierul tar.xz fișier de pe site-ul oficial și apoi instalați-l manual. Înainte de aceasta, trebuie să instalăm unele dependențe necesare.

Construirea și instalarea dependențelor

sudo apt install build-essential checkinstall

sudo apt install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev

Descărcarea și instalarea manuală a versiunii Python necesare

cd /opt && sudo wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz

sudo tar -xvf Python-3.6.6.tar.xz

cd Python-3.6.6/

sudo ./configure

sudo make && sudo make install

Se elimină fișierul descărcat

sudo rm -rf Python-3.6.6.tar.xz

Verificați versiunea Python

python3 -V
> Python 3.6.6

Configurarea utilizatorului Ubuntu pentru aplicația noastră

Django în sine este un cadru foarte sigur, sunt de acord. Dar aplicațiile web sunt încă vulnerabile. Este o bună practică să vă rulați aplicația ca utilizatori de sistem cu privilegii limitate, care au acces limitat la resursele de pe serverul dvs. Deci, în această secțiune, vom adăuga un nou grup de utilizatori și permisiuni la instanța noastră EC2.

Adăugarea grupului de sistem ubuntu „nume de grup” [webapps in my case] și atribuiți un „nume de utilizator” unui utilizator [bunny in my case] la acest grup

sudo groupadd --system webapps
sudo useradd --system --gid webapps --shell /bin/bash --home /webapps/project_name bunny

Notă: presupun „Denumirea proiectului”Este numele pe care l-ați fi folosit în timpul„django-admin startproject eu> ”

Creați un director pentru a stoca aplicația

Creați un director pentru a stoca aplicația dvs. în / webapps / project_name /. Schimbați proprietarul acelui director cu aplicația dvs. iepuraș de utilizator:

sudo mkdir -p /webapps/project_name/

sudo chown bunny /webapps/project_name/

Permiteți acces limitat către alți utilizatori de grup la directorul aplicației

sudo chown -R bunny:users /webapps/project_name

sudo chmod -R g+w /webapps/project_name

Acum puteți trece la utilizatorul dvs.

sudo su - bunny

// your console will switch to something like this
bunny@ip-172-31-5-231:~$

Pentru a reveni la sudo utilizator, doar fă ctrl+d și va ucide terminalul utilizatorului.

Instalarea și configurarea PostgresSQL

Instalarea PostgreSQL și crearea bazei de date

sudo apt install postgresql postgresql-contrib

sudo su - postgres

postgres@ip-172-31-5-231:~$ psql

postgres=# CREATE DATABASE database_name;

Schimbarea parolei implicite pentru postgres în timp ce vă aflați în psql Terminal

postgres=# password

Implementați aplicația Django pe instanța EC2 prin Git în mediu virtual

Implementarea aplicației dvs. utilizând un mediu virtual permite aplicației dvs. și cerințelor sale să fie gestionate separat. Este o bună practică să vă mențineți aplicația izolată.

Utilizarea conceptului de mediu este la îndemână atunci când implementați mai multe aplicații Django într-o singură instanță pentru a le menține izolate una de alta și dependențele lor.

Vom crea un mediu virtual în utilizatorul sistemului nostru (iepuraș) director. Înainte de aceasta, vom instala git ca un sudo utilizator.

Instalarea Git și extragerea codului dvs. din git repo

sudo apt-get install git

sudo su - bunny

// change to your repo https or ssh link
bunny@ip-172-31-5-231:~$ git remote add origin 

git@github.com:<user>/<user-repo>.git

bunny@ip-172-31-5-231:~$ git pull origin <branch_name>

Rețineți că nu am clonat repo completarea noastră aici. În schimb, ne-am setat manual linkul git și am tras doar ramura pe care dorim să o implementăm în această instanță. Este posibil să aveți o instanță diferită pentru aplicația dvs. web de dezvoltare, beta sau pregătită pentru producție, corespunzătoare fiecărei ramuri de pe git.

Crearea unui mediu virtual folosind Python3.6 în directorul curent

bunny@ip-172-31-5-231:~$ python3.6 -m venv .
bunny@ip-172-31-5-231:~$ source bin/activate
(project_name)bunny@ip-172-31-5-231:~$ pip install -r requirements.txt

În acest moment, am creat cu succes proiectul nostru. Acum trebuie să rulăm câteva gestiona.py comanda. Acest lucru va necesita să ne aflăm în directorul unde este prezent manage.py sau de fiecare dată când trebuie să îi oferim o cale:

(project_name)bunny@ip-172-31-5-231:~$ python <path-to->manage.py migrate

(project_name)bunny@ip-172-31-5-231:~$ python <path-to->manage.py createsuperuser

(project_name)bunny@ip-172-31-5-231:~$ python <path-to->manage.py collectstatic

Notă: collectstatic comanda necesită configurarea STATIC corectă. Totuși, nu discutăm aici, deoarece nu se află în sfera acestui tutorial.

(project_name)bunny@ip-172-31-5-231:~$ python <path-to->manage.py runserver 0.0.0.0:8000

Aceasta va porni serverul de dezvoltare pe port 8000. Presupunând că portul 8000 este, de asemenea, deschis pentru instanța dvs., puteți vizita numele de domeniu al serverului sau adresa IP, urmată de 8000 în browserul dvs.

http://your_server_domain_or_public_IP:8000
http://your_server_domain_or_public_IP:8000/admin

Notă: Nu uitați să adăugați domeniul sau adresa IP la ALLOWED_HOST în settings.py

Configurarea serverului de aplicații uWSGI

Acum că avem proiectul configurat și gata de pornire, putem configura uWSGI pentru a ne servi aplicația pe web în locul serverului de dezvoltare ușor oferit de Django.

Dacă vă gândiți să rulați comanda runserver pe un ecran, aruncați-o. Serverul de dezvoltare cu Django este teribil de ușor, extrem de nesigur și nu este scalabil.

Puteți instala uWSGI fie în virtualenv, fie la nivel global și îl puteți configura corespunzător.

În acest tutorial, vom instala uWSGI în virtualenv. Înainte de a putea instala uWSGI, avem nevoie de fișierele de dezvoltare Python pe care se bazează software-ul.

Instalarea uWSGI împreună cu dependențele sale

sudo apt-get install python3-dev
sudo su - bunny
bunny@ip-172-31-5-231:~$ source bin/activate
(project_name)bunny@ip-172-31-5-231:~$ pip install uwsgi

Să rulăm serverul folosind uWSGI. Această comandă face același lucru a manage.py rulează serverul ar face. Trebuie să înlocuiți valorile în consecință pentru a testa cu succes cu această comandă.

(project_name)bunny@ip-172-31-5-231:~$ uwsgi --http :8000 --home <path-to-virtualenv> --chdir <path-to-manage.py-dir> -w <project-name>.wsgi

Crearea fișierului de configurare uWSGI

Rularea uWSGI din linia de comandă este utilă numai pentru testare. Pentru implementarea efectivă, vom crea un .ini fișier undeva în directorul de utilizator al sistemului nostru. Acest fișier va conține toată configurația pentru gestionarea unei solicitări grele și poate fi modificat în consecință.

Mai târziu în acest tutorial, vom rula uWSGI în spatele NGINX. NGINX este extrem de compatibil cu uWSGI și are suport încorporat pentru interacțiunea cu uWSGI.

Creați un director conf în directorul utilizatorului de sistem în care veți stoca uwsgi.ini

(project_name)bunny@ip-172-31-5-231:~$ mkdir conf
(project_name)bunny@ip-172-31-5-231:~$ cd conf
(project_name)bunny@ip-172-31-5-231:~$ nano uwsgi.ini

Copiați codul de mai jos din gist și salvați-l. Cred că comentariile sunt suficient de explicative pentru fiecare opțiune.

NOTĂ: updateMe ar trebui să fie numele proiectului dvs. Este același nume pe care l-ați dat mai sus în timp ce creați directorul utilizatorului sistemului, așa că actualizați în consecință.

[uwsgi]

# telling user to execute file
uid = bunny

# telling group to execute file
gid = webapps

# name of project you during "django-admin startproject <name>"
project_name = updateMe

# building base path to where project directory is present [In my case this dir is also where my virtual env is]
base_dir = /webapps/%(project_name)

# set PYTHONHOME/virtualenv or setting where my virtual enviroment is
virtualenv = %(base_dir)

# changig current directory to project directory where manage.py is present
chdir = %(base_dir)/src/

# loading wsgi module
module =  %(project_name).wsgi:application

# enabling master process with n numer of child process
master = true
processes = 4

# enabling multithreading and assigning threads per process
# enable-threads  = true
# threads = 2

# Enable post buffering past N bytes. save to disk all HTTP bodies larger than the limit $
post-buffering = 204800

# Serialize accept() usage (if possibie).
thunder-lock = True


# Bind to the specified socket using default uwsgi protocol.
uwsgi-socket = %(base_dir)/run/uwsgi.sock

# set the UNIX sockets’ permissions to access
chmod-socket = 666

# Set internal sockets timeout in seconds.
socket-timeout = 300

# Set the maximum time (in seconds) a worker can take to reload/shutdown.
reload-mercy = 8

# Reload a worker if its address space usage is higher than the specified value (in megabytes).
reload-on-as = 512

# respawn processes taking more than 50 seconds
harakiri = 50

# respawn processes after serving 5000 requests
max-requests = 5000

# clear environment on exit
vacuum = true

# When enabled (set to True), only uWSGI internal messages and errors are logged.
disable-logging = True

# path to where uwsgi logs will be saved
logto = %(base_dir)/log/uwsgi.log

# maximum size of log file 20MB
log-maxsize = 20971520

# Set logfile name after rotation.
log-backupname = %(base_dir)/log/old-uwsgi.log

# Reload uWSGI if the specified file or directory is modified/touched.
touch-reload = %(base_dir)/src/

# Set the number of cores (CPUs) to allocate to each worker process.
# cpu-affinity = 1

# Reload workers after this many seconds. Disabled by default.
max-worker-lifetime = 300

Încerc să fac totul ușor cu explicații clare. Verificați căile încrucișate, numele directorului și alte intrări pe care vi se cere să le înlocuiți.

Trebuie să creăm fișierul jurnal și să rulăm directorul în care va fi creat fișierul nostru socket, pe care tocmai l-am menționat în uwsgi.ini:

(project_name)bunny@ip-172-31-5-231:~$ mkdir log
(project_name)bunny@ip-172-31-5-231:~$ mkdir run
(project_name)bunny@ip-172-31-5-231:~$ touch log/uwsgi.log

Asigurați-vă că modificați permisiunile pentru aceste două astfel încât fiecare grup sau utilizator să poată scrie sau executa fișiere în aceste directoare:

$ sudo chmod 777 /webapps/updateMe/run
$ sudo chmod 777 /webapps/updateMe/log

Acum să încercăm să rulăm serverul folosind uwsgi.ini pe care tocmai l-am creat.

(project_name)bunny@ip-172-31-5-231:~$ uwsgi --ini /webapps/updateMe/conf/uwsgi.ini

Dacă totul până acum este configurat corect, atunci ar trebui să ruleze. Dacă nu, atunci trebuie să vă întoarceți pentru a verifica orice ați pierdut (cum ar fi calea / numele proiectului etc.).

Pentru a verifica orice jurnal uswgi puteți pisică sau coadă uwsgi.log:

(project_name)bunny@ip-172-31-5-231:~$ tail log/uwsgi.log

Creați un fișier de unitate systemd pentru uWSGI

În acest moment, dacă totul este grozav, puteți rula chiar și această comandă ecran și detașează-l – dar din nou, aceasta nu este deloc o bună practică. În schimb, vom crea un serviciu de sistem și vom permite systemd (Managerul de servicii Ubuntu) are grijă de el.

Reveniți la sudo user

$ sudo nano /etc/systemd/system/uwsgi.service

și copiați codul de lipire din esența de mai jos. Nu uitați să actualizați și să controlați numele / calea care se potrivesc aplicației dvs.:

[Unit]
Description=uWSGI instance to serve updateMe project
After=network.target

[Service]
User=bunny
Group=webapps
WorkingDirectory=/webapps/project_name/src
Environment="PATH=/webapps/project_name/bin"
ExecStart=/webapps/project_name/bin/uwsgi --ini /webapps/project_name/conf/uwsgi.ini
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

După ce salvați fișierul de mai sus și îl închideți, puteți rula următoarele comenzi:

Reîncărcați demonul systemctl pentru a reîncărca configurația managerului systemd și a recrea întregul arbore de dependență

$ sudo systemctl daemon-reload

Activați serviciul uwsgi pentru a porni la repornirea sistemului

$ sudo systemctl enable uwsgi

Porniți serviciul uwsgi

$ sudo service uwsgi start

Reporniți serviciul uwsgi

$ sudo service uwsgi restart

Verificați starea serviciului uwsgi

$ sudo service uwsgi status

Respirați adânc aici dacă totul a decurs fără probleme. Tocmai am terminat de configurat cea mai agitată parte a acestui tutorial, așa că ar trebui să fii mândru.

Apoi vom configura NGINX și apoi vom termina! Știu că acest lucru durează puțin, dar credeți-mă – odată ce ați terminat, veți fi la fel de fericiți ca și mine după publicarea acestui tutorial.

Configurarea NGINX pe EC2 pentru uWSGI

NGINX este un server ușor și îl vom folosi ca un proxy invers.

Am putea lăsa uWSGI să ruleze direct pe portul 80, dar NGINX are mult mai multe beneficii ceea ce îl face de dorit. De asemenea, NGINX include în mod nativ a sustine pentru uWSGI.

Destul de vorbit, să instalăm NGINX în instanța noastră

$ sudo apt-get install nginx

Acum, când mergi la http: // adresa-IP-sau-publică, veți vedea o pagină de întâmpinare Nginx. Acest lucru se datorează faptului că NGINX ascultă portul 80 conform configurației sale implicite.

NGINX are două directoare, site-uri disponibile și activat de site-uri, care au nevoie de atenția noastră. site-uri disponibile stochează toate fișierele conf pentru toate site-urile disponibile pe acea instanță. site-uri activate stochează linkul simbolic pentru fiecare site activat către directorul site-uri disponibile.

În mod implicit, există un singur fișier conf denumit implicit care are configurarea de bază pentru NGINX. Puteți să îl modificați sau să creați unul nou. În cazul nostru, îl voi șterge:

$ sudo rm -rf /etc/nginx/sites-available/default
$ sudo rm -rf /etc/nginx/sites-enabled/default

Să ne creăm nginx-uwsgi.conf fișier pentru a conecta solicitarea browserului la serverul uwsgi pe care îl rulăm în site-disponibil:

$ sudo nano /etc/nginx/sites-available/nginx-uwsgi.conf

și copiați următorul cod din esența de mai jos:

upstream updateMe_dev {
    server unix:/webapps/updateMe/run/uwsgi.sock;
}

server {
    listen 80;
    server_name your-IP-or-address-here;
    charset utf-8;

    client_max_body_size 128M;

    location /static {
    # exact path to where your static files are located on server 
    # [mostly you won't need this, as you will be using some storage service for same]
        alias /webapps/updateMe/static_local;
    }

    location /media {
    # exact path to where your media files are located on server 
    # [mostly you won't need this, as you will be using some storage service for same]
        alias /webapps/updateMe/media_local;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass updateMe_dev;
        uwsgi_read_timeout 300s;
        uwsgi_send_timeout 300s;
    }

    access_log /webapps/updateMe/log/dev-nginx-access.log;
    error_log /webapps/updateMe/log/dev-nginx-error.log;
}
$ sudo ln -s /etc/nginx/sites-available/nginx-uwsgi.conf /etc/nginx/sites-enabled/nginx-uwsgi.conf

Atât, suntem aproape acolo, pe cale să terminăm …

Reîncărcați daemonul systemctl

$ sudo systemctl daemon-reload

Activați serviciul nginx la repornirea sistemului

$ sudo systemctl enable nginx

Porniți serviciul Nginx

$ sudo service nginx start

Testează Nginx. Ar trebui să revină OK, cu succes ca parte a rezultatului.

$ sudo nginx -t

Dacă NGINX eșuează, puteți verifica ultimul său jurnal de erori sau jurnal de acces pe calea specificată de noi în conf.

$ tail -f /webapps/updateMe/log/nginx-error.log
$ tail -f /webapps/updateMe/log/nginx-access.log

Reporniți serviciul Nginx

$ sudo service nginx restart

Verificați starea serviciului Nginx

$ sudo service nginx status

Acum ar trebui să puteți accesa aplicația dvs. la http: // adresa-IP-sau-publică

Ei bine, acesta este sfârșitul acestui tutorial lung. Sper că ai primit ceea ce te așteptai de la el. Mulțumesc că ai purtat cu mine.

PS: uWSGI + NGINX + Django este foarte personalizabil pentru a îndeplini orice cerințe la scară largă. Acestea fiind spuse, optimizarea de bază se află încă la nivel de aplicație. Modul în care codificați și utilizați interogarea Django ORM sau Raw SQL etc. vă va ajuta în continuare.