Cách cung cấp các ứng dụng Django với uWSGI và Nginx trên Ubuntu 16.04
Django là một khung công tác web mạnh mẽ có thể giúp bạn khởi động ứng dụng Python hoặc trang web của bạn . Django bao gồm một server phát triển được đơn giản hóa để kiểm tra mã local của bạn, nhưng đối với bất kỳ thứ gì thậm chí liên quan đến production một chút, cần phải có một web server mạnh mẽ và an toàn hơn.Trong hướng dẫn này, ta sẽ trình bày cách cài đặt và cấu hình một số thành phần trên Ubuntu 16.04 để hỗ trợ và phục vụ các ứng dụng Django. Ta sẽ cấu hình server chứa ứng dụng uWSGI để giao tiếp với các ứng dụng của ta . Sau đó, ta sẽ cài đặt Nginx để đảo ngược proxy tới uWSGI, cấp cho ta quyền truy cập vào các tính năng bảo mật và hiệu suất của nó để phục vụ các ứng dụng của ta .
Yêu cầu và Mục tiêu
Để hoàn thành hướng dẫn này, bạn nên có version server Ubuntu 16.04 mới với user không phải root có quyền sudo
cấu hình . Bạn có thể tìm hiểu cách cài đặt điều này bằng cách chạy qua hướng dẫn cài đặt server ban đầu của ta .
Ta sẽ cài đặt Django trong hai môi trường ảo khác nhau. Điều này sẽ cho phép các dự án của bạn và các yêu cầu của chúng được xử lý riêng biệt. Ta sẽ tạo hai dự án mẫu để ta có thể chạy qua các bước trong môi trường đa dự án.
Sau khi có các ứng dụng của bạn , ta sẽ cài đặt và cấu hình server ứng dụng uWSGI. Điều này sẽ đóng role là giao diện cho các ứng dụng của ta , nó sẽ dịch các yêu cầu của khách hàng bằng cách sử dụng các lệnh gọi HTTP sang Python mà ứng dụng của ta có thể xử lý. Sau đó, ta sẽ cài đặt Nginx trước uWSGI để tận dụng các cơ chế xử lý kết nối hiệu suất cao và các tính năng bảo mật dễ triển khai của nó.
Bắt đầu nào.
Cài đặt và cấu hình VirtualEnv và VirtualEnvWrapper
Ta sẽ cài đặt các dự án Django của ta trong môi trường ảo của riêng chúng để tách biệt các yêu cầu cho từng dự án. Để làm điều này, ta sẽ cài đặt virtualenv
, có thể tạo môi trường ảo Python và virtualenvwrapper
, bổ sung một số cải tiến về khả năng sử dụng cho quy trình làm việc virtualenv
.
Ta sẽ cài đặt cả hai thành phần này bằng cách sử dụng pip
, trình quản lý gói Python. Ta có thể cài đặt tiện ích này từ repository Ubuntu.
Nếu bạn đang xây dựng các dự án Django của bạn bằng Python 2 , hãy nhập:
- sudo apt-get update
- sudo apt-get install python-pip
Nếu bạn đang sử dụng Python 3 , hãy nhập:
- sudo apt-get update
- sudo apt-get install python3-pip
Đến đây bạn đã cài đặt pip
, ta có thể cài đặt virtualenv
và virtualenvwrapper
trên phạm vi global . Ta cũng sẽ nâng cấp pip
lên version mới nhất bằng chính pip
.
Nếu bạn đang sử dụng Python 2 , hãy nhập:
- sudo -H pip install --upgrade pip
- sudo -H pip install virtualenv virtualenvwrapper
Nếu bạn đang sử dụng Python 3 , hãy nhập:
- sudo -H pip3 install --upgrade pip
- sudo -H pip3 install virtualenv virtualenvwrapper
Với các thành phần này được cài đặt, bây giờ ta có thể cấu hình shell của bạn với thông tin nó cần để hoạt động với tập lệnh virtualenvwrapper
. Tất cả các môi trường ảo của ta sẽ được đặt trong một folder trong folder chính có tên là Env
để dễ dàng truy cập. Điều này được cấu hình thông qua một biến môi trường có tên là WORKON_HOME
. Ta có thể thêm nó vào script khởi tạo shell của bạn và có thể tạo nguồn cho script wrapper của môi trường ảo.
Nếu bạn đang sử dụng Python 3 và lệnh pip3
, bạn cũng sẽ phải thêm một dòng bổ sung vào tập lệnh khởi tạo shell của bạn :
- echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc
Dù bạn đang sử dụng version Python nào, bạn cần chạy các lệnh sau:
- echo "export WORKON_HOME=~/Env" >> ~/.bashrc
- echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc
Bây giờ, hãy mã nguồn tập lệnh khởi tạo shell của bạn để bạn có thể sử dụng chức năng này trong phiên hiện tại của bạn :
- source ~/.bashrc
Đến đây bạn sẽ có folder tên là Env
trong folder chính của bạn, folder này sẽ chứa thông tin môi trường ảo.
Tạo dự án Django
Bây giờ ta đã có các công cụ môi trường ảo, ta sẽ tạo hai môi trường ảo, cài đặt Django trong mỗi môi trường và bắt đầu hai dự án.
Tạo dự án đầu tiên
Ta có thể tạo môi trường ảo một cách dễ dàng bằng cách sử dụng một số lệnh mà tập lệnh virtualenvwrapper
cung cấp cho ta .
Tạo môi trường ảo đầu tiên của bạn với tên của trang web hoặc dự án đầu tiên của bạn bằng lệnh :
- mkvirtualenv firstsite
Điều này sẽ tạo ra một môi trường ảo, cài đặt Python và pip
bên trong nó, và kích hoạt môi trường. Dấu nhắc của bạn sẽ thay đổi để cho biết rằng bạn hiện đang hoạt động trong môi trường ảo mới của bạn . Nó sẽ giống như sau: ( firstsite ) user @ hostname :~$
. Giá trị trong ngoặc đơn là tên của môi trường ảo của bạn. Mọi phần mềm được cài đặt thông qua pip
bây giờ sẽ được cài đặt vào môi trường ảo thay vì trên hệ thống global . Điều này cho phép ta tách các gói của bạn trên cơ sở từng dự án.
Bước đầu tiên của ta sẽ là cài đặt chính Django. Ta có thể sử dụng pip
cho việc này mà không cần sudo
vì ta đang cài đặt local này trong môi trường ảo của ta :
- pip install django
Với Django được cài đặt, ta có thể tạo dự án mẫu đầu tiên của bạn bằng lệnh :
- cd ~
- django-admin.py startproject firstsite
Thao tác này sẽ tạo một folder có tên là firstsite
trong folder chính của bạn. Trong phần này là một kịch bản quản lý được sử dụng để xử lý các khía cạnh khác nhau của dự án và một folder khác cùng tên được sử dụng để chứa mã dự án thực tế.
Chuyển vào folder cấp đầu tiên để ta có thể bắt đầu cài đặt các yêu cầu tối thiểu cho dự án mẫu của bạn .
- cd ~/firstsite
Bắt đầu bằng cách di chuyển database để khởi tạo database SQLite mà dự án của ta sẽ sử dụng. Bạn có thể cài đặt database thay thế cho ứng dụng của bạn nếu muốn, nhưng điều này nằm ngoài phạm vi của hướng dẫn này:
- ~/firstsite/manage.py migrate
Đến đây bạn sẽ có một file database có tên db.sqlite3
trong folder dự án của bạn. Bây giờ, ta có thể tạo admin-user bằng lệnh :
- ~/firstsite/manage.py createsuperuser
Đến đây, folder dự án của bạn ( ~/ firstsite
trong trường hợp của ta ) sẽ có nội dung sau:
-
~/firstsite/manage.py
: Một tập lệnh quản lý dự án Django. -
~/firstsite/firstsite/
: Gói dự án Django. Điều này phải chứa các file__init__.py
,settings.py
,urls.py
vàwsgi.py
-
~/firstsite/db.sqlite3
: Tệp database SQLite được sử dụng để lưu trữ thông tin trang web .
Tiếp theo, mở file cài đặt cho dự án bằng editor của bạn:
- nano ~/firstsite/firstsite/settings.py
Bắt đầu bằng cách định vị chỉ thị ALLOWED_HOSTS
. Điều này xác định danh sách các địa chỉ hoặc domain của server được dùng để kết nối với version Django. Bất kỳ yêu cầu nào đến có tiêu đề Server lưu trữ không có trong danh sách này sẽ dẫn đến một ngoại lệ. Django yêu cầu bạn cài đặt điều này để ngăn chặn một lớp lỗ hổng bảo mật nhất định.
Trong dấu ngoặc vuông, liệt kê các địa chỉ IP hoặc domain được liên kết với server Django của bạn. Mỗi mục nên được liệt kê trong phần trích dẫn với các mục được phân tách bằng dấu phẩy. Nếu bạn muốn có yêu cầu cho toàn bộ domain và bất kỳ domain phụ nào, hãy thêm một khoảng thời gian vào đầu mục nhập. Trong đoạn mã dưới đây, có một vài ví dụ được comment được sử dụng để chứng minh:
. . . # The simplest case: just add the domain name(s) and IP addresses of your Django server # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5'] # To respond to 'example.com' and any subdomains, start the domain with a dot # ALLOWED_HOSTS = ['.example.com', '203.0.113.5'] ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . .]
Vì ta sẽ cài đặt Nginx để phục vụ trang web của bạn , ta cần cấu hình một folder sẽ chứa các tài sản tĩnh của trang web của ta . Điều này sẽ cho phép Nginx phục vụ những thứ này trực tiếp, điều này sẽ có tác động tích cực đến hiệu suất. Ta sẽ yêu cầu Django đặt chúng vào một folder được gọi là static
trong folder cơ sở của dự án của ta . Thêm dòng này vào cuối file để cấu hình hành vi này:
. . . STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Lưu file khi bạn hoàn tất. Bây giờ, hãy thu thập các phần tử tĩnh của trang web của ta và đặt chúng trong folder đó bằng lệnh :
- ~/firstsite/manage.py collectstatic
Bạn có thể được yêu cầu nhập “yes” để xác nhận hành động và thu thập nội dung tĩnh. Sẽ có một folder mới được gọi là static
trong folder dự án của bạn.
Tiếp theo, ta có thể mở một cổng để có thể truy cập vào server phát triển Django. Nếu bạn đã làm theo hướng dẫn cài đặt server ban đầu, bạn nên bật firewall UFW. Cho phép kết nối với cổng 8080 bằng lệnh :
- sudo ufw allow 8080
Với tất cả những điều đó, ta có thể kiểm tra dự án của bạn bằng cách tạm thời khởi động server phát triển. Kiểu:
- ~/firstsite/manage.py runserver 0.0.0.0:8080
Thao tác này sẽ khởi động server phát triển trên cổng 8080
. Truy cập domain hoặc địa chỉ IP của server của bạn, theo sau là 8080
trong trình duyệt của bạn:
http://server_domain_or_IP:8080
Bạn sẽ thấy một trang trông như thế này:
Thêm /admin
vào cuối URL trong thanh địa chỉ của trình duyệt và bạn sẽ được đưa đến trang đăng nhập quản trị:
Sử dụng thông tin đăng nhập quản trị mà bạn đã chọn bằng lệnh createsuperuser
, đăng nhập vào server . Sau đó, bạn sẽ có quyền truy cập vào giao diện quản trị:
Sau khi thử nghiệm chức năng này, hãy dừng server phát triển bằng lệnh CTRL-C vào terminal của bạn. Bây giờ ta có thể chuyển sang dự án thứ hai của bạn .
Tạo dự án thứ hai
Dự án thứ hai sẽ được tạo theo cách giống hệt như dự án đầu tiên. Ta sẽ rút ngắn lời giải thích trong phần này, xem như cách bạn đã hoàn thành việc này một lần.
Di chuyển trở lại folder chính của bạn và tạo một môi trường ảo thứ hai cho dự án mới của bạn. Cài đặt Django bên trong môi trường mới này sau khi nó được kích hoạt:
- cd ~
- mkvirtualenv secondsite
- pip install django
Môi trường mới sẽ được tạo và thay đổi thành môi trường ảo trước đó của bạn. Phiên bản Django này hoàn toàn tách biệt với version khác mà bạn đã cấu hình . Điều này cho phép bạn quản lý chúng một cách độc lập và tùy chỉnh khi cần thiết.
Tạo dự án thứ hai và chuyển vào folder dự án:
- cd ~
- django-admin.py startproject secondsite
- cd ~/secondsite
Khởi tạo database và tạo admin-user :
- ~/secondsite/manage.py migrate
- ~/secondsite/manage.py createsuperuser
Mở file cài đặt:
- nano ~/secondsite/secondsite/settings.py
Đặt ALLOWED_HOSTS
thành domain của dự án thứ hai của bạn, địa chỉ IP của server hoặc cả hai, giống như bạn đã làm với dự án đầu tiên:
ALLOWED_HOSTS = ['second_project_domain_or_IP', 'another_domain_or_IP', . . .]
Thêm vị trí cho các file tĩnh, giống như bạn đã làm trong dự án trước:
. . . STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Lưu và đóng file . Bây giờ, hãy thu thập các phần tử tĩnh vào folder đó bằng lệnh :
- ~/secondsite/manage.py collectstatic
Cuối cùng, kích hoạt server phát triển để kiểm tra trang web:
- ~/secondsite/manage.py runserver 0.0.0.0:8080
Bạn nên kiểm tra trang web thường xuyên tại:
http://server_domain_or_IP:8080
Đồng thời đăng nhập vào trang quản trị:
http://server_domain_or_IP:8080/admin
Khi bạn đã xác nhận mọi thứ đang hoạt động như mong đợi, hãy nhập CTRL-C vào terminal của bạn để dừng server phát triển.
Backup khỏi môi trường ảo
Vì bây giờ ta đã hoàn tất phần Django của hướng dẫn, ta có thể hủy kích hoạt môi trường ảo thứ hai của bạn :
- deactivate
Nếu bạn cần làm việc lại trên một trong hai trang web Django của bạn , bạn nên chạy lại môi trường tương ứng của chúng. Bạn có thể thực hiện bằng cách sử dụng lệnh workon
:
- workon firstsite
Hoặc là:
- workon secondsite
, hãy hủy kích hoạt khi bạn làm việc xong trên các trang web của bạn :
- deactivate
Bây giờ ta có thể chuyển sang cấu hình server ứng dụng.
Cài đặt server ứng dụng uWSGI
Bây giờ ta đã cài đặt hai dự án Django và sẵn sàng hoạt động, ta có thể cấu hình uWSGI. uWSGI là một server ứng dụng có thể giao tiếp với các ứng dụng qua giao diện tiêu chuẩn được gọi là WSGI. Để tìm hiểu thêm về điều này, hãy đọc phần này trong hướng dẫn của ta về cách cài đặt uWSGI và Nginx trên Ubuntu 14.04.
Cài đặt uWSGI
Không giống như hướng dẫn được liên kết ở trên, trong hướng dẫn này, ta sẽ cài đặt uWSGI trên phạm vi global . Điều này sẽ tạo ra ít ma sát hơn trong việc xử lý nhiều dự án Django. Trước khi có thể cài đặt uWSGI, ta cần các file phát triển Python mà phần mềm dựa vào. Ta có thể cài đặt cái này trực tiếp từ kho của Ubuntu.
Nếu bạn đang sử dụng Django với Python 2 , hãy nhập:
- sudo apt-get install python-dev
Nếu bạn đang sử dụng Python 3 , hãy nhập:
- sudo apt-get install python3-dev
Bây giờ các file phát triển đã có sẵn, ta có thể cài đặt uWSGI trên phạm vi global thông qua pip
.
Nếu bạn đang sử dụng Python 2 , hãy nhập:
- sudo -H pip install uwsgi
Nếu bạn đang sử dụng Python 3 , hãy nhập:
- sudo -H pip3 install uwsgi
Ta có thể nhanh chóng kiểm tra server ứng dụng này bằng cách chuyển nó thông tin cho một trong các trang web của ta . Ví dụ: ta có thể yêu cầu nó phục vụ dự án đầu tiên của ta bằng lệnh :
- uwsgi --http :8080 --home /home/sammy/Env/firstsite --chdir /home/sammy/firstsite -w firstsite.wsgi
Ở đây, ta đã yêu cầu uWSGI sử dụng môi trường ảo nằm trong folder ~/Env
của ta , để thay đổi thành folder của dự án và sử dụng file wsgi.py
được lưu trữ trong folder firstsite
bên trong của ta để phân phát file (sử dụng trang firstsite.wsgi
Cú pháp module Python). Đối với phần trình diễn của ta , ta đã yêu cầu nó phân phát HTTP trên cổng 8080
.
Nếu bạn truy cập domain hoặc địa chỉ IP của server trong trình duyệt của bạn , theo sau là :8080
, bạn sẽ thấy lại trang web của bạn (các phần tử tĩnh trong giao diện /admin
, như CSS, sẽ không hoạt động). Khi bạn hoàn tất việc kiểm tra chức năng này, hãy nhập CTRL-C vào terminal .
Tạo file cấu hình
Chạy uWSGI từ dòng lệnh rất hữu ích để thử nghiệm, nhưng không đặc biệt hữu ích cho việc triển khai thực tế. Thay vào đó, ta sẽ chạy uWSGI ở “Chế độ hoàng đế”, cho phép một quy trình chính quản lý các ứng dụng riêng biệt một cách tự động với một tập hợp các file cấu hình.
Tạo một folder chứa các file cấu hình của bạn. Vì đây là một quy trình global , ta sẽ tạo một folder có tên /etc/uwsgi/sites
để lưu trữ các file cấu hình của ta :
- sudo mkdir -p /etc/uwsgi/sites
Trong folder này, ta sẽ đặt các file cấu hình của ta . Ta cần một file cấu hình cho từng dự án mà ta đang phục vụ. Quá trình uWSGI có thể lấy các file cấu hình ở nhiều định dạng khác nhau, nhưng ta sẽ sử dụng file .ini
do tính đơn giản của chúng.
Tạo một file cho dự án đầu tiên của bạn và mở nó trong editor của bạn:
- sudo nano /etc/uwsgi/sites/firstsite.ini
Bên trong, ta phải bắt đầu với tiêu đề phần [uwsgi]
. Tất cả thông tin của ta sẽ nằm bên dưới tiêu đề này. Ta cũng sẽ sử dụng các biến để làm cho file cấu hình của ta có thể tái sử dụng nhiều hơn. Sau tiêu đề, hãy đặt một biến có tên là project
với tên của dự án đầu tiên của bạn. Thêm một biến có tên uid
chứa tên user sudo
của bạn.
Ta cũng sẽ thêm một biến được gọi là base
với đường dẫn đến folder chính của user của bạn. Điều này sẽ được xây dựng từ tên user mà ta đặt bằng cú pháp %(variable_name)
. Điều này sẽ được thay thế bằng giá trị của biến khi cấu hình được đọc:
[uwsgi] project = firstsite uid = sammy base = /home/%(uid)
Tiếp theo, ta cần cấu hình uWSGI để nó xử lý dự án của ta một cách chính xác. Ta cần thay đổi folder dự án root bằng cách cài đặt tùy chọn chdir
. Ta có thể kết hợp folder chính và tên dự án bằng cách sử dụng cùng một cú pháp biến.
Theo cách tương tự, ta sẽ chỉ ra môi trường ảo cho dự án của ta . Bằng cách cài đặt module , ta có thể chỉ ra chính xác cách giao tiếp với dự án của bạn ( bằng lệnh “ứng dụng” có thể gọi từ file wsgi.py
trong folder dự án bên trong của ta ). Cấu hình của các mục này sẽ giống như sau:
[uwsgi] project = firstsite uid = sammy base = /home/%(uid) chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application
Ta muốn tạo ra một quy trình tổng thể với 5 công nhân. Ta có thể làm điều này bằng cách thêm điều này:
[uwsgi] project = firstsite uid = sammy base = /home/%(uid) chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application master = true processes = 5
Tiếp theo, ta cần chỉ định cách uWSGI sẽ lắng nghe các kết nối. Trong thử nghiệm của ta về uWSGI, ta đã sử dụng HTTP và một cổng mạng. Tuy nhiên, vì ta sẽ sử dụng Nginx làm Reverse Proxy nên ta có các tùy chọn tốt hơn.
Thay vì sử dụng cổng mạng, vì tất cả các thành phần đều hoạt động trên một server duy nhất, ta có thể sử dụng socket Unix. Điều này an toàn hơn và mang lại hiệu suất tốt hơn. Ổ cắm này sẽ không sử dụng HTTP mà thay vào đó sẽ triển khai giao thức uwsgi
của uwsgi
, là một giao thức binary nhanh được thiết kế để giao tiếp với các server khác. Nginx có thể ủy quyền tự nhiên bằng giao thức uwsgi
, vì vậy đây là lựa chọn tốt nhất của ta .
Ta cũng sẽ sửa đổi quyền sở hữu và quyền của socket vì ta sẽ cấp cho web server quyền ghi. Ta sẽ đặt tùy chọn vacuum
để file socket sẽ tự động được dọn dẹp khi dịch vụ bị dừng:
[uwsgi] project = firstsite uid = sammy base = /home/%(uid) chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application master = true processes = 5 socket = /run/uwsgi/%(project).sock chown-socket = %(uid):www-data chmod-socket = 660 vacuum = true
Với điều này, cấu hình uWSGI của dự án đầu tiên của ta đã hoàn tất. Lưu và đóng file .
Ưu điểm của việc cài đặt file bằng cách sử dụng các biến là nó làm cho nó cực kỳ đơn giản để sử dụng lại. Sao chép file cấu hình của dự án đầu tiên của bạn để sử dụng làm cơ sở cho file cấu hình thứ hai của bạn:
- sudo cp /etc/uwsgi/sites/firstsite.ini /etc/uwsgi/sites/secondsite.ini
Mở file cấu hình thứ hai bằng editor của bạn:
- sudo nano /etc/uwsgi/sites/secondsite.ini
Ta chỉ cần thay đổi một giá trị duy nhất trong file này để làm cho nó hoạt động cho dự án thứ hai của ta . Sửa đổi biến project
với tên bạn đã sử dụng cho dự án thứ hai của bạn :
[uwsgi] project = secondsite uid = sammy base = /home/%(uid) chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application master = true processes = 5 socket = /run/uwsgi/%(project).sock chown-socket = %(uid):www-data chmod-socket = 660 vacuum = true
Lưu file khi bạn hoàn tất. Dự án thứ hai của bạn đã sẵn sàng để thực hiện ngay bây giờ.
Tạo file đơn vị systemd cho uWSGI
Bây giờ ta có các file cấu hình mà ta cần để phục vụ các dự án Django của bạn , nhưng ta vẫn chưa tự động hóa quy trình. Tiếp theo, ta sẽ tạo một file đơn vị systemd để quản lý quy trình hoàng đế uWSGI và tự động khởi động uWSGI khi khởi động.
Ta sẽ tạo file đơn vị trong folder /etc/systemd/system
, nơi lưu giữ file đơn vị do administrator tạo. Ta sẽ gọi file của ta là uwsgi.service
:
- sudo nano /etc/systemd/system/uwsgi.service
Bắt đầu với phần [Unit]
, được sử dụng để chỉ định metadata và thông tin đặt hàng. Ta chỉ cần đặt một mô tả về dịch vụ của ta ở đây:
[Unit] Description=uWSGI Emperor service
Tiếp theo, ta sẽ mở phần [Service]
. Ta sẽ sử dụng chỉ thị ExecStartPre
để cài đặt các phần ta cần để chạy server của bạn . Điều này sẽ đảm bảo folder /run/uwsgi
được tạo và user bình thường của ta sở hữu nó với www-data
group với quyền là chủ sở hữu group . Cả mkdir
với cờ -p
và lệnh chown
trả về thành công ngay cả khi thao tác của chúng không cần thiết. Đây là những gì ta muốn.
Đối với lệnh bắt đầu thực tế, được chỉ định bởi chỉ thị ExecStart
, ta sẽ trỏ đến file thực thi uwsgi
. Ta sẽ yêu cầu nó chạy ở “Chế độ hoàng đế”, cho phép nó quản lý nhiều ứng dụng bằng các file mà nó tìm thấy trong /etc/uwsgi/sites
. Ta cũng sẽ thêm các phần cần thiết để systemd quản lý đúng quy trình. Chúng được lấy từ tài liệu uWSGI ở đây .
[Unit] Description=uWSGI Emperor service [Service] ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown sammy:www-data /run/uwsgi' ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites Restart=always KillSignal=SIGQUIT Type=notify NotifyAccess=all
Bây giờ, tất cả những gì ta cần làm là thêm phần [Install]
. Điều này cho phép ta chỉ định khi nào dịch vụ sẽ được tự động khởi động. Ta sẽ gắn dịch vụ của bạn với trạng thái hệ thống nhiều user . Khi nào hệ thống được cài đặt cho nhiều user (điều kiện hoạt động bình thường), dịch vụ của ta sẽ được kích hoạt:
[Unit] Description=uWSGI Emperor service [Service] ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown sammy:www-data /run/uwsgi' ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites Restart=always KillSignal=SIGQUIT Type=notify NotifyAccess=all [Install] WantedBy=multi-user.target
Khi bạn hoàn tất, hãy lưu file .
Ta sẽ không thể bắt đầu dịch vụ thành công tại thời điểm này vì nó phụ thuộc vào user www-data
có sẵn. Ta sẽ phải đợi để bắt đầu dịch vụ uWSGI cho đến sau khi Nginx được cài đặt.
Cài đặt và cấu hình Nginx làm Reverse Proxy
Với uWSGI được cấu hình và sẵn sàng hoạt động, giờ đây ta có thể cài đặt và cấu hình Nginx làm Reverse Proxy của ta . Điều này có thể được download từ repository mặc định của Ubuntu:
- sudo apt-get install nginx
Khi Nginx được cài đặt, ta có thể tiếp tục và tạo file cấu hình khối server cho từng dự án của bạn . Bắt đầu với dự án đầu tiên bằng cách tạo file cấu hình khối server :
- sudo nano /etc/nginx/sites-available/firstsite
Bên trong, ta có thể bắt đầu khối server của bạn bằng cách chỉ ra số cổng và domain mà dự án đầu tiên của ta có thể truy cập được. Khối server_name
phải trùng với một trong các domain của server hoặc địa chỉ IP của nó, nếu không, trang Nginx mặc định được dùng thay thế. Ta sẽ giả định bạn có một domain cho mỗi:
server { listen 80; server_name firstsite.com www.firstsite.com; }
Tiếp theo, ta có thể nói với Nginx đừng lo lắng nếu nó không thể tìm thấy biểu tượng yêu thích. Ta cũng sẽ trỏ nó đến vị trí của folder file tĩnh, nơi ta đã thu thập các phần tử tĩnh của trang web:
server { listen 80; server_name firstsite.com www.firstsite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/sammy/firstsite; } }
Tiếp theo, ta có thể tạo một khối vị trí nhận tất cả sẽ chuyển tất cả các truy vấn bổ sung đến thẳng ứng dụng của ta . Ta sẽ bao gồm các tham số uwsgi
được tìm thấy trong /etc/nginx/uwsgi_params
và chuyển lưu lượng truy cập đến socket mà server uWSGI cài đặt :
server { listen 80; server_name firstsite.com www.firstsite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/sammy/firstsite; } location / { include uwsgi_params; uwsgi_pass unix:/run/uwsgi/firstsite.sock; } }
Như vậy, khối server đầu tiên của ta đã hoàn tất.
Ta sẽ sử dụng điều này làm cơ sở cho file cấu hình Nginx của dự án thứ hai của ta . Sao chép nó ngay bây giờ:
- sudo cp /etc/nginx/sites-available/firstsite /etc/nginx/sites-available/secondsite
Mở file mới trong editor của bạn:
- sudo nano /etc/nginx/sites-available/secondsite
Tại đây, bạn sẽ phải thay đổi bất kỳ tham chiếu nào đến trang firstsite
bằng tham chiếu đến trang secondsite
. Bạn cũng sẽ phải sửa đổi server_name
để dự án thứ hai của bạn đáp ứng với một domain khác hoặc thay đổi cổng nếu bạn không có nhiều domain hoặc địa chỉ IP. Khi bạn hoàn thành, nó sẽ trông giống như sau:
server { listen 80; server_name secondsite.com www.secondsite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/sammy/secondsite; } location / { include uwsgi_params; uwsgi_pass unix:/run/uwsgi/secondsite.sock; } }
Lưu file khi bạn hoàn tất.
Tiếp theo, liên kết cả hai file cấu hình mới của bạn với folder sites-enabled
của Nginx để kích hoạt chúng:
- sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled
- sudo ln -s /etc/nginx/sites-available/secondsite /etc/nginx/sites-enabled
Kiểm tra cú pháp cấu hình bằng lệnh :
- sudo nginx -t
Nếu không phát hiện thấy lỗi cú pháp nào, bạn có thể khởi động lại dịch vụ Nginx của bạn để tải cấu hình mới:
- sudo systemctl restart nginx
Nếu bạn nhớ trước đó, ta chưa bao giờ thực sự khởi động server uWSGI. Làm điều đó ngay bây giờ bằng lệnh :
- sudo systemctl start uwsgi
Hãy xóa luật UFW đến cổng 8080
và thay vào đó cho phép truy cập vào server Nginx của ta :
- sudo ufw delete allow 8080
- sudo ufw allow 'Nginx Full'
Đến đây bạn có thể tiếp cận hai dự án của bạn bằng cách truy cập domain tương ứng của chúng. Cả giao diện công khai và quản trị sẽ hoạt động như mong đợi.
Nếu điều này diễn ra tốt đẹp, bạn có thể cho phép cả hai dịch vụ tự động khởi động khi server khởi động bằng lệnh :
- sudo systemctl enable nginx
- sudo systemctl enable uwsgi
Sau khi cấu hình Nginx, bước tiếp theo phải đảm bảo lưu lượng truy cập vào server bằng SSL / TLS. Điều này rất quan trọng vì không có nó, tất cả thông tin, bao gồm cả password được gửi qua mạng ở dạng văn bản thuần túy.
Nếu bạn có domain , cách dễ nhất để có được certificate SSL đảm bảo lưu lượng truy cập của bạn là sử dụng Let's Encrypt. Làm theo hướng dẫn này để cài đặt Let's Encrypt with Nginx trên Ubuntu 16.04.
Nếu bạn không có domain , bạn vẫn có thể bảo mật trang web của bạn để thử nghiệm và học hỏi bằng chứng chỉ SSL tự ký .
Khắc phục sự cố Nginx và uWSGI
Nếu bạn không thể truy cập ứng dụng của bạn , bạn cần khắc phục sự cố cài đặt của bạn .
Nginx đang hiển thị trang mặc định thay vì ứng dụng Django
Nếu Nginx hiển thị các trang mặc định thay vì proxy để ứng dụng của bạn, nó thường nghĩa là bạn cần phải điều chỉnh server_name
trong /etc/nginx/sites-available/ firstsite
file để trỏ đến địa chỉ IP của server của bạn hoặc domain .
Nginx sử dụng server_name
để xác định khối server nào sẽ sử dụng để phản hồi các yêu cầu. Nếu bạn nhìn thấy trang Nginx mặc định, đó là dấu hiệu cho thấy Nginx không thể khớp yêu cầu với khối server một cách rõ ràng, vì vậy nó đang rơi trở lại khối mặc định được xác định trong /etc/nginx/sites-available/default
.
server_name
trong khối server của dự án của bạn phải cụ thể hơn tên trong khối server mặc định được chọn.
Nginx đang hiển thị lỗi 502 Bad Gateway thay vì ứng dụng Django
Lỗi 502 cho biết Nginx không thể ủy quyền thành công yêu cầu. Một loạt các sự cố cấu hình tự biểu hiện bằng lỗi 502, vì vậy cần có thêm thông tin để khắc phục sự cố đúng cách.
Nơi chính để tìm kiếm thêm thông tin là trong log lỗi của Nginx. Nói chung, điều này sẽ cho bạn biết những điều kiện nào gây ra sự cố trong sự kiện ủy quyền. Theo dõi log lỗi Nginx bằng lệnh :
- sudo tail -F /var/log/nginx/error.log
Bây giờ, hãy thực hiện một yêu cầu khác trong trình duyệt của bạn để tạo ra một lỗi mới (thử làm mới trang). Bạn sẽ thấy một thông báo lỗi mới được ghi vào log . Nếu bạn nhìn vào thông báo, nó sẽ giúp bạn thu hẹp vấn đề.
Bạn có thể thấy một số thông báo sau:
kết nối () với unix: /run/uwsgi/firstsite.sock không thành công (2: Không có file hoặc folder như vậy)
Điều này cho thấy rằng Nginx không thể tìm thấy file socket tại vị trí nhất định. Bạn nên so sánh uwsgi_pass
vị trí được định nghĩa trong firstsite
và secondsite
file trong /etc/nginx/sites-available
file đến vị trí thực tế của firstsite.sock
và secondsite.sock
file socket trong /run/uwsgi
folder .
Kiểm tra sự tồn tại của các file socket trong folder /run/uwsgi
bằng lệnh :
- sudo ls /run/uwsgi
Nếu không có file socket nào trong /run/uwsgi
, điều đó thường nghĩa là quá trình uwsgi
không thể tạo nó. Kiểm tra trạng thái của quá trình uwsgi
để tìm hiểu xem nó có thể bắt đầu hay không:
- sudo systemctl status uwsgi
Nếu lệnh systemctl status
cho biết đã xảy ra lỗi hoặc nếu bạn không tìm thấy file socket trong folder , thì đó là dấu hiệu cho thấy uWSGI không thể khởi động chính xác. Kiểm tra log quy trình uWSGI bằng lệnh :
- sudo journalctl -u uwsgi
Hãy xem các thông báo trong log để tìm hiểu xem uWSGI đã gặp sự cố ở đâu. Có nhiều lý do mà bạn có thể gặp phải sự cố, nhưng thông thường, nếu uWSGI không thể tạo file socket, đó là vì một trong những lý do sau:
- Các file dự án thuộc sở hữu của user
root
thay vì usersudo
- Dòng
ExecStartPre
trong file/etc/systemd/system/uwsgi.service
không bao gồm lệnh chính xác để tạo folder và gán quyền sở hữu - Đường dẫn
uwsgi_pass
trong file cấu hình trang web trong folder/etc/nginx/sites-available
không nhắm đến đúng vị trí socket - Cấu hình uWSGI được xác định trong các file
.ini
trong folder/etc/uwsgi/sites
không chính xác. Kiểm tra các mục sau:- Chỉ thị
chdir
, sau khi được nội suy, trỏ đến folder chính của dự án. - Chỉ thị
home
, sau khi được nội suy, trỏ đến folder môi trường ảo. - Chỉ thị
module
sử dụng cú pháp nhập module Python để tải filewsgi.py
từ trong folder dự án bên trong. - Chỉ thị
socket
trỏ đến một file trong file/run/uwsgi
(tệp đó sẽ được tạo bởi dòngExecStartPre
trong file dịch vụ được đề cập ở trên).
- Chỉ thị
Nếu bạn thực hiện thay đổi đối với file /etc/systemd/system/uwsgi.service
, hãy reload daemon để đọc lại định nghĩa dịch vụ và khởi động lại quy trình uWSGI bằng lệnh :
- sudo systemctl daemon-reload
- sudo systemctl restart uwsgi
Việc khắc phục những sự cố này sẽ cho phép Nginx tìm thấy file socket một cách chính xác.
connect () với unix: /run/uwsgi/firstsite.sock không thành công (13: Quyền bị từ chối)
Điều này cho thấy rằng Nginx không thể kết nối với socket uWSGI do các vấn đề về quyền. Thông thường, điều này xảy ra khi socket đang được tạo trong một môi trường bị hạn chế hoặc nếu các quyền bị sai. Trong khi quy trình uWSGI có thể tạo file socket , Nginx không thể truy cập file đó.
Điều này có thể xảy ra nếu có các quyền hạn chế tại bất kỳ điểm nào giữa folder root ( /
) file socket. Ta có thể thấy các quyền và giá trị quyền sở hữu của file socket và từng folder mẹ của nó bằng cách chuyển đường dẫn tuyệt đối đến file socket của ta tới lệnh namei
:
- namei -nom /run/uwsgi/firstsite.sock
Outputf: /run/uwsgi/firstsite.sock drwxr-xr-x root root / drwxr-xr-x root root run drwxr-xr-x sammy www-data uwsgi srw-rw---- sammy www-data firstsite.sock
Đầu ra hiển thị các quyền của từng thành phần folder . Bằng cách xem xét các quyền (cột đầu tiên), chủ sở hữu (cột thứ hai) và chủ sở hữu group (cột thứ ba), ta có thể tìm ra loại quyền truy cập nào được phép đối với file socket.
Trong ví dụ trên, mỗi folder dẫn đến file socket có quyền đọc và thực thi thế giới (cột quyền cho các folder kết thúc bằng rx
thay vì ---
). Group www-data
có quyền sở hữu group đối với chính socket . Với các cài đặt này, quá trình Nginx sẽ có thể truy cập thành công socket .
Nếu bất kỳ folder nào dẫn đến socket không thuộc quyền sở hữu của group www-data
hoặc không có quyền đọc và thực thi thế giới, Nginx sẽ không thể truy cập socket . Thông thường, điều này nghĩa là các file cấu hình có lỗi.
Nếu các đường dẫn folder quá hạn chế quyền hoặc quyền sở hữu, hãy xem file /etc/systemd/system/uwsgi.service
. Chỉ thị ExecStartPre
chịu trách nhiệm tạo folder /run/uwsgi
và gán quyền sở hữu group cho group www-data
. Nếu các lệnh ở đây không đúng, các đường dẫn folder có thể quá hạn chế.
Nếu bản thân file socket không thể truy cập được vào tiến trình Nginx , cài đặt được xác định trong file .ini
bên trong /etc/uwsgi/sites
có thể không chính xác. Kiểm tra các giá trị của chown-socket
và chmod-socket
đảm bảo rằng quy trình web được cấp quyền truy cập các file .
Khắc phục sự cố thêm
Để khắc phục sự cố bổ sung, log có thể giúp thu hẹp các nguyên nhân root rễ. Lần lượt kiểm tra từng cái và tìm kiếm thông báo chỉ ra các khu vực có vấn đề.
Các bản ghi sau đây có thể hữu ích:
- Kiểm tra log tiến trình Nginx bằng lệnh :
sudo journalctl -u nginx
- Kiểm tra log truy cập Nginx bằng lệnh :
sudo less /var/log/nginx/access.log
- Kiểm tra log lỗi Nginx bằng lệnh :
sudo less /var/log/nginx/error.log
- Kiểm tra log ứng dụng uWSGI bằng lệnh :
sudo journalctl -u uwsgi
Khi cập nhật cấu hình hoặc ứng dụng của bạn , bạn có thể cần phải khởi động lại các quy trình để điều chỉnh các thay đổi của bạn .
Nếu cập nhật ứng dụng Django của bạn , bạn có thể khởi động lại quy trình uWSGI để nhận các thay đổi bằng lệnh :
- sudo systemctl restart uwsgi
Nếu bạn thay đổi file dịch vụ uwsgi
systemd, hãy reload daemon và khởi động lại quá trình bằng lệnh :
- sudo systemctl daemon-reload
- sudo systemctl restart uwsgi
Nếu bạn thay đổi cấu hình khối server Nginx, hãy kiểm tra cấu hình rồi đến Nginx bằng lệnh :
- sudo nginx -t && sudo systemctl restart nginx
Các lệnh này hữu ích để chọn các thay đổi khi bạn điều chỉnh cấu hình của bạn .
Kết luận
Trong hướng dẫn này, ta đã cài đặt hai dự án Django, mỗi dự án trong môi trường ảo của riêng chúng. Ta đã cấu hình uWSGI để phục vụ từng dự án một cách độc lập bằng cách sử dụng môi trường ảo được cấu hình cho từng dự án. Sau đó, ta cài đặt Nginx hoạt động như một Reverse Proxy để xử lý các kết nối của client và phục vụ đúng dự án tùy thuộc vào yêu cầu của khách hàng.
Django làm cho việc tạo các dự án và ứng dụng trở nên đơn giản bằng cách cung cấp nhiều phần chung, cho phép bạn tập trung vào các yếu tố độc đáo. Bằng cách tận dụng chuỗi công cụ chung được mô tả trong bài viết này, bạn có thể dễ dàng phục vụ các ứng dụng bạn tạo từ một server duy nhất.
Các tin liên quan
Cách cài đặt Nginx trên Ubuntu 16.042016-04-21
Cách tạo chứng chỉ SSL tự ký cho Nginx trong Ubuntu 16.04
2016-04-21
Cách cài đặt Discourse Behind Nginx trên Ubuntu 14.04
2016-04-19
Cách thiết lập Nginx với Hỗ trợ HTTP / 2 trên Ubuntu 16.04
2016-04-12
Cách thêm module gzip vào Nginx trên CentOS 7
2016-03-15
Cách thêm module gzip vào Nginx trên Ubuntu 14.04
2016-03-09
Cách thiết lập xác thực HTTP cơ bản với Nginx trên Ubuntu 14.04
2016-02-22
Cách thiết lập xác thực HTTP cơ bản với Nginx trên CentOS 7
2016-02-22
Cách bảo mật Nginx trên Ubuntu 14.04
2016-02-12
Cách bảo mật Nginx bằng Let's Encrypt trên CentOS 7
2016-01-26