
Svaki put pokretanje poslužitelja za novi projekt može potrajati ili biti teško za nove programere. Stoga sam mislio napisati detaljni vodič koji će olakšati postupak implementacije.
Ako niste raspoloženi za čitanje, možete kopirati svaki korak zalijepiti kako je opisano (zamijeniti vrijednosti) i pokrenuti svoj poslužitelj?
Preduvjeti:
- Primjer Amazon Linux EC2 pokrenut i pokrenut s povezanim parom ključeva ( ssh pristup njemu ).
- Port 22, 80 mora biti otvoren za ovaj slučaj.
- Django aplikacija koju želite implementirati.
- Postavke baze podataka konfigurirane su za upotrebu PostgreSQL-a.
- requirements.txt prisutan je u vašoj aplikaciji i ima popis ovisnosti za instaliranje.
- Git spremište za vašu aplikaciju Django.
SSH i ažuriranje instance ubuntu-a
Trebate ući u vašu instancu EC2, zato provjerite imate li otvoren port 22 za svoju instancu, a zatim izvršite ažuriranje / nadogradnju.
ssh -i path-to-your-key.pem [email protected] sudo apt-get update && sudo apt-get upgrade -y
Instaliranje Python3.6.x na AWS EC2 (ubuntu 16.04)
Datoteku tar.xz preuzet ćemo sa službene stranice, a zatim ćemo je ručno instalirati. Prije toga moramo instalirati neke potrebne ovisnosti.
Izgradnja i instaliranje ovisnosti
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
Preuzimanje i ručno instaliranje potrebne verzije Pythona
cd /opt && sudo wget //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
Uklanjanje preuzete datoteke
sudo rm -rf Python-3.6.6.tar.xz
Provjerite verziju Pythona
python3 -V > Python 3.6.6
Postavljanje Ubuntu korisnika za našu aplikaciju
Django je sam po sebi vrlo siguran okvir, slažem se. No, web aplikacije su i dalje ranjive. Dobra je praksa pokretati svoju aplikaciju kao korisnici sustava s ograničenim privilegijama koji imaju ograničen pristup resursima na vašem poslužitelju. Dakle, u ovom ćemo odjeljku dodati novu grupu korisnika i dopuštenja u našu instancu EC2.
Dodavanje ubuntu sistemske grupe 'naziv grupe' [webapps u mom slučaju] i dodijeljivanje korisničkog imena '[zeka u mom slučaju] ovoj grupi
sudo groupadd --system webapps sudo useradd --system --gid webapps --shell /bin/bash --home /webapps/project_name bunny
Napomena: Pretpostavljam da je " ime_projekta " ime koje ste možda koristili tijekom " django-admin startproject
Izradite direktorij za pohranu svoje aplikacije
Stvorite direktorij za pohranu vaše aplikacije u / webapps / project_name /. Promijenite vlasnika tog direktorija u zeca korisnika aplikacije:
sudo mkdir -p /webapps/project_name/ sudo chown bunny /webapps/project_name/
Omogućite ograničeni pristup drugim korisnicima grupe direktoriju aplikacija
sudo chown -R bunny:users /webapps/project_name sudo chmod -R g+w /webapps/project_name
Sada se možete prebaciti na svog korisnika
sudo su - bunny // your console will switch to something like this [email protected]:~$
Da biste se vratili na sudo korisnika, samo učinite ctrl+d
i ubit će korisnički terminal.
Instaliranje i konfiguriranje PostgresSQL
Instaliranje PostgreSQL-a i stvaranje baze podataka
sudo apt install postgresql postgresql-contrib sudo su - postgres [email protected]:~$ psql postgres=# CREATE DATABASE database_name;
Promjena zadane lozinke za postgres dok je u psql terminalu
postgres=# \password
Postavite aplikaciju Django na instancu EC2 putem Gita u virtualnom okruženju
Primjenom aplikacije pomoću virtualnog okruženja omogućuje se odvojeno rukovanje aplikacijom i njezinim zahtjevima. Dobra je praksa držati svoju aplikaciju izoliranom.
Korištenje koncepta okoliša je korisno kada na jednoj instanci instalirate više od jedne Django aplikacije kako biste ih i njihove ovisnosti međusobno izolirali.
Stvorit ćemo virtualno okruženje u direktoriju našeg korisnika ( zeka ). Prije toga instalirat ćemo git kao sudo korisnik.
Instaliranje Gita i povlačenje koda iz git repo-a
sudo apt-get install git sudo su - bunny // change to your repo https or ssh link [email protected]:~$ git remote add origin [email protected]:/.git [email protected]:~$ git pull origin
Imajte na umu da ovdje nismo klonirali svoj cjeloviti repo. Umjesto toga, ručno smo postavili našu git vezu i povukli samo granu koju želimo rasporediti na ovu instancu. Možda imate drugačiju instancu za vašu web-aplikaciju za razvoj, beta ili produkciju koja odgovara svakoj grani na git-u.
Stvaranje virtualnog okruženja pomoću Python3.6 u trenutnom direktoriju
[email protected]:~$ python3.6 -m venv . [email protected]:~$ source bin/activate (project_name)[email protected]:~$ pip install -r requirements.txt
U ovom smo trenutku uspješno postavili naš projekt. Sada moramo pokrenuti neku naredbu manage.p y . To će zahtijevati da se nalazimo u direktoriju gdje je prisutan naš manage.py ili svaki put kad mu trebamo dati put:
(project_name)[email protected]:~$ python manage.py migrate (project_name)[email protected]:~$ python manage.py createsuperuser (project_name)[email protected]:~$ python manage.py collectstatic
Note: collectstatic
command requires that the STATIC configuration is setup properly. We are not discussing that here, though, as it is not in the scope of this tutorial.
(project_name)[email protected]:~$ python manage.py runserver 0.0.0.0:8000
This will start up the development server on port 8000
. Assuming port 8000 is also open for your instance, you can visit your server's domain name or IP address followed by 8000
in your browser.
//your_server_domain_or_public_IP:8000
//your_server_domain_or_public_IP:8000/admin
Note: Don’t forget to add your domain or IP to ALLOWED_HOST in your settings.py
Setting up the uWSGI Application Server
Now that we’ve got our project set up and ready to go, we can configure uWSGI to serve our app to the web instead of the lightweight development server provided by Django.
If you’re thinking of running the runserver command on a screen, drop it. The dev server with Django is terribly lightweight, highly insecure, and not scalable.
You can install uWSGI either in virtualenv or globally and configure it accordingly.
In this tutorial, we’ll be installing uWSGI in virtualenv. Before we can install uWSGI, we need the Python development files that the software relies on.
Installing uWSGI along with its dependencies
sudo apt-get install python3-dev
sudo su - bunny
[email protected]:~$ source bin/activate
(project_name)[email protected]:~$ pip install uwsgi
Let’s run the server using uWSGI. This command does the same thing a manage.py runserver would do. You need to replace values accordingly to successfully test with this command.
(project_name)bunny@ip-172-31-5-231:~$ uwsgi --http :8000 --home --chdir -w .wsgi
Creating uWSGI configuration file
Running uWSGI from the command line is only useful for testing. For actual deployment, we will create a .inifile somewhere in our system user directory. This file will contain all the configuration for handling a heavy request load, and can be tweaked accordingly.
Later in this tutorial, we will run uWSGI behind NGINX. NGINX is highly compatible with uWSGI and has built-in support for interacting with uWSGI.
Create a directory conf in your system user directory where you will store uwsgi.ini
(project_name)[email protected]:~$ mkdir conf
(project_name)[email protected]:~$ cd conf
(project_name)[email protected]:~$ nano uwsgi.ini
Copy the below code from the gist and save it I think the comments are explanatory enough for each option.
NOTE: updateMe
is supposed to be you project name. It is the same name you gave above while creating the system user directory, so update accordingly.
[uwsgi] # telling user to execute file uid = bunny # telling group to execute file gid = webapps # name of project you during "django-admin startproject " 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
I am trying to make everything easy with clear explanations. Cross check paths, directory name, and other inputs that you are required to replace.
We need to create the log file and run directory where our socket file will be created, that we just mentioned in our uwsgi.ini:
(project_name)[email protected]:~$ mkdir log
(project_name)[email protected]:~$ mkdir run
(project_name)[email protected]:~$ touch log/uwsgi.log
Make sure to change permissions for these two so that every group or user can write or execute files in these directories:
$ sudo chmod 777 /webapps/updateMe/run
$ sudo chmod 777 /webapps/updateMe/log
Now let’s try running the server using uwsgi.ini that we just created.
(project_name)bunny@ip-172-31-5-231:~$ uwsgi --ini /webapps/updateMe/conf/uwsgi.ini
If everything up until now is setup correctly, then it should be running. If not, then you need to go back to check for anything you missed (like the path/project name, etc).
To check any uswgi log you can cat or tail uwsgi.log:
(project_name)[email protected]:~$ tail log/uwsgi.log
Create a systemd Unit File for uWSGI
At this point if everything is cool, you can even run this command in screen and detach it — but again, this is not a good practice at all. Instead we will create a system service and let systemd (Ubuntu’s service manager) take care of it.
Switch back to sudo user
$ sudo nano /etc/systemd/system/uwsgi.service
and copy paste code from the below gist. Don’t forget to update and crosscheck names/path that suit your app:
[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
After you save the above file and close it, you can run following commands:
Reload systemctl daemon to reload systemd manager configuration and recreate the entire dependency tree
$ sudo systemctl daemon-reload
Enable uwsgi service to start on system reboot
$ sudo systemctl enable uwsgi
Start uwsgi service
$ sudo service uwsgi start
Restart uwsgi service
$ sudo service uwsgi restart
Check uwsgi service status
$ sudo service uwsgi status
Take a deep breath here if everything ran smoothly. We just finished setting up most hectic part of this tutorial, so you should be proud.
Next we will setup NGINX, and then we’ll be done! I know this is taking a bit of time, but believe me — once done, you will be as happy as I will be after publishing this tutorial.
Setting Up NGINX on EC2 for uWSGI
NGINX is a lightweight server, and we’ll use it as a reverse proxy.
We could let uWSGI run directly on port 80, but NGINX has a lot more benefits which makes it desirable. Also NGINX natively includes support for uWSGI.
Enough talk, let’s install NGINX on our instance
$ sudo apt-get install nginx
Now when you go to //your-public-ip-or-address, you will see a Nginx welcome page. This is because NGINX is listening to port 80 according to its default configuration.
NGINX has two directories, sites-available and sites-enabled,that need our attention. sites-available stores all conf files for all available sites on that particular instance. sites-enabledstores the symbolic link for each enabled site to the sites-available directory.
By default, there is only one conf file named default that has basic setup for NGINX. You can either modify it or create a new one. In our case, I am going to delete it:
$ sudo rm -rf /etc/nginx/sites-available/default
$ sudo rm -rf /etc/nginx/sites-enabled/default
Let’s create our nginx-uwsgi.conf file to connect the browser request to the uwsgi server we are running in site-available:
$ sudo nano /etc/nginx/sites-available/nginx-uwsgi.conf
and copy the following code from the gist below:
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; }
Create symbolic link into sites-enabled directory for same
$ sudo ln -s /etc/nginx/sites-available/nginx-uwsgi.conf /etc/nginx/sites-enabled/nginx-uwsgi.conf
That’s all, we’re almost there, about to finish up…
Reload systemctl daemon
$ sudo systemctl daemon-reload
Enable nginx service on system reboot
$ sudo systemctl enable nginx
Start Nginx service
$ sudo service nginx start
Test Nginx. It should return OK, Successful as a part of the result.
$ sudo nginx -t
If NGINX fails, you can check its last error-log or access-log on the path specified by us in its conf.
$ tail -f /webapps/updateMe/log/nginx-error.log
$ tail -f /webapps/updateMe/log/nginx-access.log
Restart Nginx Service
$ sudo service nginx restart
Check Nginx Service status
$ sudo service nginx status
You should now be able to reach your app at //your-public-ip-or-address
Well this is the end of this lengthy tutorial. I hope you got what you expected from it. Thanks for bearing with me.
PS: uWSGI + NGINX + Django is highly customizable to meet any large scale requirements. That being said, core optimization still lies at application level. How you code and make use of Django ORM or Raw SQL query, etc. will help you further.
