Giới thiệu

Django là một khung công tác web mạnh mẽ có thể giúp bạn lấy ứng dụng hoặc trang web Python của bạn khỏi mặt đất. Django bao gồm một máy chủ phát triển đơn giản để thử nghiệm mã của bạn cục bộ, nhưng đối với bất cứ điều gì thậm chí hơi liên quan đến sản xuất, một máy chủ web an toàn hơn và mạnh mẽ là bắt buộc.

Trong hướng dẫn này, chúng tôi 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. Chúng ta sẽ cấu hình máy chủ thùng chứa ứng dụng uWSGI để giao tiếp với các ứng dụng của chúng ta. Sau đó, chúng tôi sẽ thiết lập Nginx để đảo ngược proxy với uWSGI, cho phép chúng tôi truy cập các tính năng bảo mật và hiệu suất để phục vụ các ứng dụng của chúng tôi.

Điều kiện tiên quyết và Mục tiêu

Để hoàn tất hướng dẫn này, bạn nên có một phiên bản máy chủ Ubuntu 16.04 mới với một người dùng không phải root với sudo đặc quyền được định cấu hình. Bạn có thể tìm hiểu cách thiết lập điều này bằng cách chạy qua hướng dẫn thiết lập máy chủ ban đầu.

Chúng tôi 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à yêu cầu của họ được xử lý riêng biệt. Chúng tôi sẽ tạo hai dự án mẫu để chúng tôi có thể thực hiện các bước trong môi trường đa dự án.

Khi chúng ta có các ứng dụng của mình, chúng ta sẽ cài đặt và cấu hình máy chủ ứng dụng uWSGI. Điều này sẽ phục vụ như một giao diện cho các ứng dụng của chúng tôi, 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 cuộc gọi HTTP đến Python mà ứng dụng của chúng ta có thể xử lý. Sau đó chúng tôi sẽ thiết lập Nginx trước uWSGI để tận dụng lợi thế của các cơ chế xử lý kết nối hiệu năng cao và các tính năng bảo mật dễ thực hiện của nó.

Băt đâu nao.

Cài đặt và cấu hình VirtualEnv và VirtualEnvWrapper

Chúng tôi sẽ cài đặt các dự án Django của chúng tôi trong môi trường ảo của riêng mình để cô lập các yêu cầu cho từng dự án. Để làm điều này, chúng tôi 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 khả năng sử dụng cho virtualenv dòng chảy công việc.

Chúng tôi 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. Chúng tôi có thể cài đặt tiện ích này từ kho lưu trữ Ubuntu.

Nếu bạn đang xây dựng các dự án Django của bạn với Python 2, kiểu:

sudo apt-get update

sudo apt-get install python-pip

Nếu bạn đang sử dụng Python 3, kiểu:

sudo apt-get update

sudo apt-get install python3-pip

Bây giờ bạn có pip cài đặt, chúng tôi có thể cài đặt virtualenvvirtualenvwrapper trên toàn cầu. Chúng tôi cũng sẽ nâng cấp pip lên phiên bản mới nhất bằng pip chinh no.

Nếu bạn đang sử dụng Python 2, kiểu:

sudo -H pip install --upgrade pip

sudo -H pip install virtualenv virtualenvwrapper

Nếu bạn đang sử dụng Python 3, kiểu:

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, chúng ta có thể cấu hình trình bao của chúng ta với thông tin cần thiết để làm việc với virtualenvwrapper kịch bản. Môi trường ảo của chúng ta sẽ được đặt trong một thư mục trong thư mục chính của chúng tôi 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 gọi là WORKON_HOME. Chúng ta có thể thêm điều này vào kịch bản khởi tạo shell và có thể mã nguồn kịch bản trình bao bọc môi trường ảo.

Nếu bạn đang sử dụng Python 3pip3 lệnh, bạn sẽ phải thêm một dòng bổ sung vào kịch bản khởi tạo shell của bạn:

echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc

Bất kể bạn đang sử dụng phiên bản 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 viết kịch bản 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 mình:

source ~/.bashrc

Bây giờ bạn sẽ có thư mục được gọi là Env trong thư mục chính của bạn sẽ chứa thông tin môi trường ảo.

Tạo dự án Django

Bây giờ chúng ta có các công cụ môi trường ảo của mình, chúng ta sẽ tạo ra hai môi trường ảo, cài đặt Django trong mỗi công cụ và bắt đầu hai dự án.

Tạo dự án đầu tiên

Chúng ta có thể tạo một môi trường ảo dễ dàng bằng cách sử dụng một số lệnh mà virtualenvwrapper tập lệnh có sẵn cho chúng tôi.

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 cách gõ:

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. Lời 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 mình. Nó sẽ giống như thế này: (firstsite)user@hostname:~$. Giá trị trong dấu 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 qua pip bây giờ sẽ được cài đặt vào môi trường ảo thay vì trên hệ thống toàn cầu. Điều này cho phép chúng tôi cách ly các gói của chúng tôi trên cơ sở từng dự án.

Bước đầu tiên của chúng tôi là cài đặt Django. Chúng ta có thể sử dụng pip cho điều này mà không sudo vì chúng tôi đang cài đặt cục bộ trong môi trường ảo của mình:

pip install django

Với Django được cài đặt, chúng tôi có thể tạo dự án mẫu đầu tiên của chúng tôi bằng cách gõ:

cd ~

django-admin.py startproject firstsite

Thao tác này sẽ tạo một thư mục có tên firstsite trong thư mục chính của bạn. Trong đâ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 thư mục khác cùng tên được sử dụng để chứa mã dự án thực tế.

Chuyển vào thư mục cấp đầu tiên để chúng tôi có thể bắt đầu thiết lập các yêu cầu tối thiểu cho dự án mẫu của chúng tôi.

cd ~/firstsite

Bắt đầu bằng cách di chuyển cơ sở dữ liệu để khởi tạo cơ sở dữ liệu SQLite mà dự án của chúng tôi sẽ sử dụng. Bạn có thể thiết lập một cơ sở dữ liệu thay thế cho ứng dụng của bạn nếu bạn 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

Bây giờ bạn sẽ có một tệp cơ sở dữ liệu được gọi là db.sqlite3 trong thư mục dự án của bạn. Bây giờ, chúng ta có thể tạo một người dùng quản trị bằng cách gõ:

~/firstsite/manage.py createsuperuser

Tại thời điểm này, thư mục dự án của bạn (~/firstsite trong trường hợp của chúng tôi) cần có nội dung sau:

  • ~/firstsite/manage.py: Một kịch bản quản lý dự án Django.
  • ~/firstsite/firstsite/: Gói dự án Django. Điều này sẽ chứa __init__.py, settings.py, urls.pywsgi.py các tập tin.
  • ~/firstsite/db.sqlite3: Tệp cơ sở dữ liệu SQLite được sử dụng để lưu trữ thông tin trang web của bạn.

Tiếp theo, mở tệp cài đặt cho dự án bằng trình soạn thảo văn bản của bạn:

nano ~/firstsite/firstsite/settings.py

Bắt đầu bằng cách định vị ALLOWED_HOSTS chỉ thị. Điều này định nghĩa một danh sách các địa chỉ hoặc tên miền của máy chủ có thể được sử dụng để kết nối với cá thể Django. Mọi yêu cầu đến với Máy chủ lưu trữ tiêu đề không có trong danh sách này sẽ làm tăng ngoại lệ. Django yêu cầu bạn thiết lập để ngăn chặn một lớp bảo mật nào đó.

Trong dấu ngoặc vuông, liệt kê các địa chỉ IP hoặc tên miền được liên kết với máy chủ Django của bạn. Mỗi mục phải được liệt kê trong các 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 yêu cầu cho toàn bộ miền và bất kỳ tên miền phụ nào, hãy thêm một khoảng thời gian vào đầu mục nhập. Trong đoạn dưới đây, có một vài nhận xét về các ví dụ được sử dụng để chứng minh:

~/firstsite/firstsite/settings.py

. . .
# 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ì chúng tôi sẽ thiết lập Nginx để phục vụ trang web của mình, chúng tôi cần định cấu hình thư mục sẽ giữ nội dung tĩnh của trang web của chúng tôi. Điều này sẽ cho phép Nginx phục vụ trực tiếp, điều này sẽ có tác động tích cực đến hiệu suất. Chúng tôi sẽ nói với Django để đặt chúng vào một thư mục gọi là static trong thư mục cơ sở của dự án của chúng tôi. Thêm dòng này vào cuối tệp để định cấu hình hành vi này:

~/firstsite/firstsite/settings.py

. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

Lưu và đóng tệp 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 chúng tôi và đặt chúng trong thư mục đó bằng cách gõ:

~/firstsite/manage.py collectstatic

Bạn có thể được yêu cầu nhập "có" để xác nhận hành động và thu thập nội dung tĩnh. Sẽ có một thư mục mới có tên static trong thư mục dự án của bạn.

Tiếp theo, chúng ta có thể mở một cổng để chúng ta có thể truy cập vào máy chủ phát triển Django. Nếu bạn đã làm theo hướng dẫn thiết lập máy chủ ban đầu, bạn nên bật tường lửa UFW. Cho phép kết nối tới cổng 8080 bằng cách nhập:

sudo ufw allow 8080

Với tất cả những điều đó, chúng tôi có thể kiểm tra dự án của chúng tôi bằng cách tạm thời khởi động máy chủ phát triển. Kiểu:

~/firstsite/manage.py runserver 0.0.0.0:8080

Điều này sẽ khởi động máy chủ phát triển trên cổng 8080. Truy cập tên miền hoặc địa chỉ IP của máy chủ của bạn theo sau 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:

Django sample site

Thêm vào /admin đến 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ị viên:

Django admin login

Sử dụng thông tin đăng nhập quản trị bạn đã chọn với createsuperuser lệnh, đăng nhập vào máy chủ. Sau đó, bạn sẽ có quyền truy cập vào giao diện quản trị:

Django admin interface

Sau khi thử nghiệm chức năng này, hãy ngừng máy chủ phát triển bằng cách nhập CTRL-C trong thiết bị đầu cuối của bạn. Bây giờ chúng ta có thể chuyển sang dự án thứ hai của mình.

Tạo dự án thứ hai

Dự án thứ hai sẽ được tạo giống hệt như dự án đầu tiên. Chúng tôi sẽ tóm tắt giải thích trong phần này, xem như bạn đã hoàn thành việc này một lần như thế nào.

Quay trở lại thư mục 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 khi nó được kích hoạt:

cd ~

mkvirtualenv secondsite

pip install django

Môi trường mới sẽ được tạo thay đổi thành, để lại môi trường ảo trước đó của bạn. Ví dụ Django này hoàn toàn tách biệt với cá thể khác mà bạn đã định 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à di chuyển vào thư mục dự án:

cd ~

django-admin.py startproject secondsite

cd ~/secondsite

Khởi tạo cơ sở dữ liệu và tạo người dùng quản trị:

~/secondsite/manage.py migrate

~/secondsite/manage.py createsuperuser

Mở tệp cài đặt:

nano ~/secondsite/secondsite/settings.py

Đặt ALLOWED_HOSTS vào miền dự án thứ hai của bạn, địa chỉ IP của máy chủ, 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 tệp tĩnh, giống như bạn đã làm trong dự án trước:

~/secondsite/secondsite/settings.py

. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

Lưu và đóng tập tin. Bây giờ, thu thập các phần tử tĩnh vào thư mục đó bằng cách gõ:

~/secondsite/manage.py collectstatic

Cuối cùng, kích hoạt máy chủ 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 thường 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 rằng mọi thứ đang hoạt động như mong đợi, hãy nhập CTRL-C trong thiết bị đầu cuối của bạn để dừng máy chủ phát triển.

Thoát khỏi môi trường ảo

Vì bây giờ chúng ta đã hoàn thành phần Django của hướng dẫn, chúng ta có thể hủy kích hoạt môi trường ảo thứ hai của mình:

deactivate

Nếu bạn cần phải làm việc trên một trong các trang web Django của bạn một lần nữa, bạn nên kích hoạt lại môi trường tương ứng của họ. Bạn có thể làm điều đó bằng cách sử dụng workon chỉ huy:

workon firstsite

Hoặc là:

workon secondsite

Một lần nữa, tắt khi bạn hoàn thành công việc trên trang web của mình:

deactivate

Bây giờ chúng ta có thể chuyển sang cấu hình máy chủ ứng dụng.

Thiết lập Máy chủ ứng dụng uWSGI

Bây giờ chúng ta có hai dự án Django được thiết lập và sẵn sàng để đi, chúng ta có thể cấu hình uWSGI. uWSGI là một máy chủ ứng dụng có thể giao tiếp với các ứng dụng trên một giao diện 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 thiết lập uWSGI và Nginx trên Ubuntu 14.04.

Đang 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, chúng tôi sẽ cài đặt uWSGI trên toàn cầu. Điều này sẽ tạo ra ít ma sát trong việc xử lý nhiều dự án Django. Trước khi chúng ta có thể cài đặt uWSGI, chúng ta cần các tệp phát triển Python mà phần mềm dựa vào. Chúng tôi có thể cài đặt trực tiếp từ kho lưu trữ của Ubuntu.

Nếu bạn đang sử dụng Django với Python 2, kiểu:

sudo apt-get install python-dev

Nếu bạn đang sử dụng Python 3, kiểu:

sudo apt-get install python3-dev

Giờ đây, các tệp phát triển có sẵn, chúng tôi có thể cài đặt uWSGI trên toàn cầu thông qua pip.

Nếu bạn đang sử dụng Python 2, kiểu:

sudo -H pip install uwsgi

Nếu bạn đang sử dụng Python 3, kiểu:

sudo -H pip3 install uwsgi

Chúng tôi có thể nhanh chóng kiểm tra máy chủ ứng dụng này bằng cách chuyển thông tin đó cho một trong các trang web của chúng tôi. Ví dụ, chúng tôi có thể nói nó để phục vụ dự án đầu tiên của chúng tôi bằng cách gõ:

uwsgi --http :8080 --home /home/sammy/Env/firstsite --chdir /home/sammy/firstsite -w firstsite.wsgi

Ở đây, chúng tôi đã nói với uWSGI để sử dụng môi trường ảo của chúng tôi nằm trong ~/Env thư mục, để thay đổi thư mục của dự án của chúng tôi và sử dụng wsgi.py tệp được lưu trữ bên trong bên trong của chúng tôi firstsite thư mục để phục vụ tệp (bằng cách sử dụng firstsite.wsgi Cú pháp mô-đun Python). Đối với trình diễn của chúng tôi, chúng tôi đã nói với nó để phục vụ HTTP trên cổng 8080.

Nếu bạn truy cập tên miền hoặc địa chỉ IP của máy chủ trong trình duyệt của mình, tiếp theo là :8080, bạn sẽ thấy lại trang web của mình (các phần tử tĩnh trong /admin giao diện, như CSS, sẽ không hoạt động). Khi bạn hoàn thành kiểm tra chức năng này, hãy gõ CTRL-C trong thiết bị đầu cuối.

Tạo tệp 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 đó, chúng tôi sẽ chạy uWSGI trong "chế độ Hoàng đế", cho phép quy trình tổng thể quản lý các ứng dụng riêng biệt tự động được cung cấp cho một tập hợp các tệp cấu hình.

Tạo một thư mục sẽ giữ các tập tin cấu hình của bạn. Vì đây là một quá trình toàn cầu, chúng tôi sẽ tạo một thư mục có tên /etc/uwsgi/sites để lưu trữ các tệp cấu hình của chúng tôi:

sudo mkdir -p /etc/uwsgi/sites

Trong thư mục này, chúng tôi sẽ đặt các tập tin cấu hình của chúng tôi. Chúng tôi cần một tập tin cấu hình cho từng dự án mà chúng tôi đang phục vụ. Quá trình uWSGI có thể lấy tệp cấu hình ở nhiều định dạng khác nhau, nhưng chúng tôi sẽ sử dụng .ini tệp do tính đơn giản của chúng.

Tạo một tệp cho dự án đầu tiên của bạn và mở nó trong trình soạn thảo văn bản của bạn:

sudo nano /etc/uwsgi/sites/firstsite.ini

Bên trong, chúng ta phải bắt đầu với [uwsgi] tiêu đề phần. Tất cả thông tin của chúng tôi sẽ đi bên dưới tiêu đề này. Chúng tôi cũng sẽ sử dụng các biến để làm cho tệp cấu hình của chúng tôi có thể tái sử dụng được. Sau tiêu đề, hãy đặt biến được gọi là project với tên của dự án đầu tiên của bạn. Thêm biến được gọi là uid giữ bạn sudo tên người dùng.

Chúng tôi cũng sẽ thêm một biến gọi là base với đường dẫn đến thư mục chính của người dùng. Điều này sẽ được tạo từ tên người dùng mà chúng tôi đã đặt bằng %(variable_name) cú pháp. Điều này sẽ được thay thế bằng giá trị của biến khi cấu hình được đọc:

/etc/uwsgi/sites/firstsite.ini

[uwsgi]
project = firstsite
uid = sammy
base = /home/%(uid)

Tiếp theo, chúng ta cần cấu hình uWSGI để nó xử lý chính xác dự án của chúng ta. Chúng ta cần phải thay đổi vào thư mục gốc của dự án bằng cách thiết lập chdir Tùy chọn. Chúng ta có thể kết hợp thư mục home và tên dự án bằng cách sử dụng cú pháp biến tương tự.

Theo cách tương tự, chúng tôi sẽ chỉ ra môi trường ảo cho dự án của chúng tôi. Bằng cách thiết lập mô-đun, chúng tôi có thể chỉ ra chính xác cách giao tiếp với dự án của chúng tôi (bằng cách nhập "ứng dụng" có thể gọi được từ wsgi.py trong thư mục dự án bên trong của chúng tôi). Cấu hình của các mục này sẽ trông như sau:

/etc/uwsgi/sites/firstsite.ini

[uwsgi]
project = firstsite
uid = sammy
base = /home/%(uid)

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

Chúng tôi muốn tạo ra một quy trình tổng thể với 5 công nhân. Chúng ta có thể làm điều này bằng cách thêm vào:

/etc/uwsgi/sites/firstsite.ini

[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 chúng ta cần phải xác định cách uWSGI nên lắng nghe các kết nối. Trong thử nghiệm của chúng tôi về uWSGI, chúng tôi đã sử dụng HTTP và một cổng mạng. Tuy nhiên, vì chúng ta sẽ sử dụng Nginx như một proxy ngược, chúng ta có các lựa chọn tốt hơn.

Thay vì sử dụng một cổng mạng, vì tất cả các thành phần đang hoạt động trên một máy chủ duy nhất, chúng ta có thể sử dụng một ổ cắm 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, nhưng thay vào đó sẽ thực hiện của uWSGI uwsgi giao thức, là một giao thức nhị phân nhanh được thiết kế để giao tiếp với các máy chủ khác. Nginx có thể thực sự sử dụng proxy uwsgi giao thức, vì vậy đây là lựa chọn tốt nhất của chúng tôi.

Chúng tôi cũng sẽ sửa đổi quyền sở hữu và quyền của socket vì chúng tôi sẽ cấp quyền truy cập ghi máy chủ web. Chúng tôi sẽ thiết lập vacuum tùy chọn để tệp socket sẽ tự động được dọn sạch khi dịch vụ bị dừng lại:

/etc/uwsgi/sites/firstsite.ini

[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 chúng tôi đã hoàn tất. Lưu và đóng tập tin.

Lợi thế của việc thiết lập các tập tin bằng cách sử dụng các biến là nó làm cho nó cực kỳ đơn giản để tái sử dụng. Sao chép tệp cấu hình của dự án đầu tiên của bạn để sử dụng làm cơ sở cho tệp cấu hình thứ hai của bạn:

sudo cp /etc/uwsgi/sites/firstsite.ini /etc/uwsgi/sites/secondsite.ini

Mở tệp cấu hình thứ hai bằng trình soạn thảo văn bản của bạn:

sudo nano /etc/uwsgi/sites/secondsite.ini

Chúng tôi chỉ cần thay đổi một giá trị duy nhất trong tệp này để làm cho nó hoạt động cho dự án thứ hai của chúng tôi. Sửa đổi project biến với tên bạn đã sử dụng cho dự án thứ hai của mình:

/etc/uwsgi/sites/secondsite.ini

[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 và đóng tệp khi bạn hoàn tất. Dự án thứ hai của bạn sẽ sẵn sàng để đi ngay bây giờ.

Tạo tệp đơn vị hệ thống cho uWSGI

Bây giờ chúng ta có các tập tin cấu hình cần thiết để phục vụ các dự án Django của chúng ta, nhưng chúng ta vẫn chưa tự động hóa quá trình này. Tiếp theo, chúng ta sẽ tạo một tệp đơn vị hệ thống để quản lý tiến trình hoàng đế uWSGI và tự động khởi động uWSGI khi khởi động.

Chúng tôi sẽ tạo tệp đơn vị trong /etc/systemd/system thư mục, nơi lưu giữ các tệp đơn vị do quản trị viên tạo. Chúng tôi sẽ gọi tập tin của chúng tôi uwsgi.service:

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

Bắt đầu với [Unit] , được sử dụng để chỉ định siêu dữ liệu và thông tin đặt hàng. Chúng tôi sẽ chỉ mô tả dịch vụ của chúng tôi tại đây:

/etc/systemd/system/uwsgi.service

[Unit]
Description=uWSGI Emperor service

Tiếp theo, chúng tôi sẽ mở [Service] phần. Chúng tôi sẽ sử dụng ExecStartPre chỉ thị để thiết lập các phần chúng ta cần để chạy máy chủ của chúng tôi. Điều này sẽ đảm bảo /run/uwsgi thư mục được tạo và người dùng bình thường của chúng tôi sở hữu nó với www-data nhóm làm chủ sở hữu nhóm. Cả hai mkdir với -p cờ và chown lệnh trả về thành công ngay cả khi hoạt động của họ là không cần thiết. Đây là những gì chúng ta muốn.

Đối với lệnh bắt đầu thực tế, được chỉ định bởi ExecStart chỉ thị, chúng tôi sẽ chỉ đến uwsgi thực thi. Chúng tôi sẽ yêu cầu nó chạy trong "chế độ Hoàng đế", cho phép nó quản lý nhiều ứng dụng bằng cách sử dụng các tệp mà nó tìm thấy /etc/uwsgi/sites. Chúng tôi cũng sẽ thêm các phần cần thiết cho systemd để quản lý đúng quy trình. Chúng được lấy từ tài liệu uWSGI đây.

/etc/systemd/system/uwsgi.service

[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ì chúng ta cần làm là thêm [Install] phần. Điều này cho phép chúng tôi chỉ định thời điểm dịch vụ sẽ được bắt đầu tự động. Chúng tôi sẽ liên kết dịch vụ của mình với trạng thái hệ thống nhiều người dùng. Bất cứ khi nào hệ thống được thiết lập cho nhiều người dùng (điều kiện hoạt động bình thường), dịch vụ của chúng tôi sẽ được kích hoạt:

/etc/systemd/system/uwsgi.service

[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, lưu và đóng tệp.

Chúng tôi sẽ không thể bắt đầu dịch vụ thành công vào thời điểm này bởi vì nó dựa trên www-data người dùng đang có mặt. Chúng tôi sẽ phải đợi để bắt đầu dịch vụ uWSGI cho đến khi Nginx được cài đặt.

Cài đặt và cấu hình Nginx làm Proxy ngược

Với uWSGI đã được cấu hình và sẵn sàng, chúng ta có thể cài đặt và cấu hình Nginx làm proxy ngược. Điều này có thể được tải xuống từ kho lưu trữ mặc định của Ubuntu:

sudo apt-get install nginx

Khi Nginx được cài đặt, chúng ta có thể tiếp tục và tạo một tệp cấu hình khối máy chủ cho từng dự án của chúng tôi. Bắt đầu với dự án đầu tiên bằng cách tạo một tệp cấu hình khối máy chủ:

sudo nano /etc/nginx/sites-available/firstsite

Bên trong, chúng ta có thể bắt đầu khối máy chủ của chúng tôi bằng cách chỉ ra số hiệu cổng và tên miền mà dự án đầu tiên của chúng tôi nên truy cập được. Các server_name khối phải phù hợp với một trong các tên miền của máy chủ hoặc địa chỉ IP của nó hoặc nếu không thì trang Nginx mặc định có thể được sử dụng thay thế. Giả sử bạn có một tên miền cho mỗi:

/etc/nginx/sites-available/firstsite

server {
    listen 80;
    server_name firstsite.com www.firstsite.com;
}

Tiếp theo, chúng ta có thể nói Nginx không phải lo lắng nếu nó không thể tìm thấy một favicon. Chúng tôi cũng sẽ trỏ nó đến vị trí của thư mục tệp tĩnh của chúng tôi, nơi chúng tôi đã thu thập các phần tử tĩnh của trang web của chúng tôi:

/etc/nginx/sites-available/firstsite

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, chúng ta có thể tạo một khối vị trí bắt tất cả sẽ chuyển tất cả các truy vấn bổ sung trực tiếp đến ứng dụng của chúng tôi. Chúng tôi sẽ bao gồm uwsgi các thông số được tìm thấy trong /etc/nginx/uwsgi_params và chuyển lưu lượng đến ổ cắm mà máy chủ uWSGI thiết lập:

/etc/nginx/sites-available/firstsite

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;
    }
}

Cùng với đó, khối máy chủ đầu tiên của chúng tôi đã hoàn tất.

Chúng tôi sẽ sử dụng điều này làm cơ sở cho tệp cấu hình Nginx của dự án thứ hai của chúng tôi. Sao chép nó bây giờ:

sudo cp /etc/nginx/sites-available/firstsite /etc/nginx/sites-available/secondsite

Mở tệp mới trong trình chỉnh sửa văn bản của bạn:

sudo nano /etc/nginx/sites-available/secondsite

Ở đây, bạn sẽ phải thay đổi bất kỳ tham chiếu nào firstsite với một tham chiếu đến secondsite. Bạn cũng sẽ phải sửa đổi server_name để dự án thứ hai của bạn phản hồi một tên miền khác hoặc thay đổi cổng nếu bạn không có nhiều hơn một tên miền hoặc địa chỉ IP. Khi bạn hoàn thành, nó sẽ trông giống như sau:

/etc/nginx/sites-available/secondsite

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 và đóng tệp khi bạn hoàn tất.

Tiếp theo, liên kết cả hai tệp cấu hình mới của bạn với Nginx sites-enabled để bậ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 cách gõ:

sudo nginx -t

Nếu không phát hiện lỗi cú pháp, bạn có thể khởi động lại dịch vụ Nginx để tải cấu hình mới:

sudo systemctl restart nginx

Nếu bạn nhớ từ trước đó, chúng tôi không bao giờ thực sự bắt đầu máy chủ uWSGI. Làm điều đó ngay bây giờ bằng cách gõ:

sudo systemctl start uwsgi

Hãy xóa quy tắc UFW thành cổng 8080 và thay vào đó cho phép truy cập vào máy chủ Nginx của chúng tôi:

sudo ufw delete allow 8080

sudo ufw allow 'Nginx Full'

Bây giờ bạn có thể tiếp cận hai dự án của mình bằng cách chuyển đến tên miền tương ứng của chúng. Cả giao diện công cộng và quản trị đều hoạt động như mong đợi.

Nếu điều này diễn ra tốt đẹp, bạn có thể kích hoạt cả hai dịch vụ để khởi động tự động khi khởi động bằng cách gõ:

sudo systemctl enable nginx

sudo systemctl enable uwsgi

Note

Sau khi cấu hình Nginx, bước tiếp theo cần bảo vệ lưu lượng đến máy chủ bằng SSL / TLS. Điều này là quan trọng bởi vì không có nó, tất cả thông tin, bao gồm cả mật khẩu được gửi qua mạng trong văn bản thuần túy.

Nếu bạn có một tên miền, cách dễ nhất có được một chứng chỉ SSL để đảm bảo lưu lượng truy cập của bạn là sử dụng Let's Encrypt. Theo hướng dẫn này để thiết lập Hãy mã hóa với Nginx trên Ubuntu 16.04.

Nếu bạn không có tên miền, bạn vẫn có thể bảo mật trang web của bạn để thử nghiệm và học tập với 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 vào ứng dụng của mình, bạn sẽ cần khắc phục sự cố cài đặt của mình.

Nginx đang hiển thị trang mặc định thay vì ứng dụng Django

Nếu Nginx hiển thị trang mặc định thay vì ủy quyền cho ứng dụng của bạn, nó thường có nghĩa là bạn cần điều chỉnh server_name trong /etc/nginx/sites-available/firstsite để trỏ đến địa chỉ IP hoặc tên miền của máy chủ của bạn.

Nginx sử dụng server_name để xác định khối máy chủ nào sẽ sử dụng để trả lời các yêu cầu. Nếu bạn đang 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 một khối sever một cách rõ ràng, vì vậy nó rơi trở lại khối mặc định được định nghĩa trong /etc/nginx/sites-available/default.

Các server_name trong khối máy chủ của dự án của bạn phải cụ thể hơn so với khối máy chủ mặc định được chọn.

Nginx đang hiển thị lỗi cổng lỗi 502 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 vấn đề cấu hình thể hiện bản thân với lỗi 502, do đó, cần có thêm thông tin để khắc phục sự cố đúng cách.

Địa điểm chính để tìm thêm thông tin nằm trong nhật ký lỗi của Nginx. Nói chung, điều này sẽ cho bạn biết điều kiện nào gây ra sự cố trong sự kiện proxy. Theo dõi các bản ghi lỗi Nginx bằng cách gõ:

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 lỗi mới (hãy 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 nhật ký. Nếu bạn nhìn vào tin nhắn, 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:

connect () thành unix: /run/uwsgi/firstsite.sock không thành công (2: Không có tệp hoặc thư mục nào)

Điều này cho thấy Nginx không thể tìm thấy tệp socket tại vị trí đã cho. Bạn nên so sánh uwsgi_pass vị trí được xác định trong firstsitesecondsite tệp trong /etc/nginx/sites-available tệp đến vị trí thực tế của firstsite.socksecondsite.sock các tệp ổ cắm trong /run/uwsgi danh mục.

Kiểm tra sự tồn tại của các tệp socket trong /run/uwsgi thư mục bằng cách gõ:

sudo ls /run/uwsgi

Nếu không có tệp ổ cắm nào trong /run/uwsgi, nó thường có nghĩa là uwsgi quá trình không thể tạo ra nó. Kiểm tra trạng thái của uwsgi quá trình để tìm hiểu xem nó có thể bắt đầu:

sudo systemctl status uwsgi

Nếu systemctl status lệnh chỉ ra rằng một lỗi xảy ra hoặc nếu bạn không tìm thấy các tập tin ổ cắm trong thư mục, đó là một dấu hiệu cho thấy uWSGI đã không thể bắt đầu chính xác. Kiểm tra nhật ký quy trình uWSGI bằng cách gõ:

sudo journalctl -u uwsgi

Hãy xem các thông điệp trong nhật ký để tìm hiểu nơi uWSGI gặp sự cố. Có nhiều lý do khiến bạn có thể gặp sự cố, nhưng thường, nếu uWSGI không thể tạo tệp socket, đó là vì một trong những lý do sau:

  • Các tệp dự án được sở hữu bởi root người dùng thay vì sudo người dùng
  • Các ExecStartPre dòng trong /etc/systemd/system/uwsgi.service tệp không bao gồm lệnh đúng để tạo thư mục và gán quyền sở hữu
  • Các uwsgi_pass đường dẫn trong các tệp cấu hình trang web trong /etc/nginx/sites-available thư mục không nhằm vào vị trí ổ cắm chính xác
  • Cấu hình uWSGI được định nghĩa trong .ini các tệp trong /etc/uwsgi/sites thư mục không chính xác. Kiểm tra các mục sau:
    • Các chdir chỉ thị, một khi được nội suy, trỏ vào thư mục dự án chính.
    • Các home chỉ thị, một khi được nội suy, trỏ vào thư mục môi trường ảo.
    • Các module chỉ thị sử dụng cú pháp nhập khẩu mô-đun Python để tải wsgi.py tệp từ bên trong thư mục dự án bên trong.
    • Các socket chỉ thị chỉ một tệp trong /run/uwsgi tệp (cần được tạo bởi ExecStartPre dòng trong tệp dịch vụ được đề cập ở trên).

Nếu bạn thực hiện thay đổi đối với /etc/systemd/system/uwsgi.service tập tin, tải lại daemon để đọc lại định nghĩa dịch vụ và khởi động lại quá trình uWSGI bằng cách gõ:

sudo systemctl daemon-reload

sudo systemctl restart uwsgi

Việc khắc phục các vấn đề này sẽ cho phép Nginx tìm đúng tệp ổ cắm.

connect () thành 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 Nginx không thể kết nối với socket uWSGI vì các vấn đề về quyền hạn. Thông thường, điều này xảy ra khi ổ cắm đang được tạo trong một môi trường bị hạn chế hoặc nếu các điều khoản bị sai. Trong khi quá trình uWSGI có thể tạo tệp socket, Nginx không thể truy cập nó.

Điều này có thể xảy ra nếu có quyền hạn chế tại bất kỳ điểm nào giữa thư mục gốc (/) tệp socket. Chúng ta có thể thấy các quyền hạn và các giá trị quyền sở hữu của tệp socket và mỗi thư mục cha của nó bằng cách chuyển đường dẫn tuyệt đối tới tệp socket của chúng ta tới namei chỉ huy:

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 thư mục. 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 nhóm (cột thứ ba), chúng ta có thể tìm ra loại truy cập nào được cho phép vào tệp socket.

Trong ví dụ trên, mỗi thư mục dẫn đến tệp socket đều có quyền đọc và thực thi trên thế giới (cột quyền cho các thư mục kết thúc bằng r-x thay vì ---). Các www-data nhóm có quyền sở hữu nhóm trên chính socket đó. Với các cài đặt này, quá trình Nginx sẽ có thể truy cập vào ổ cắm thành công.

Nếu bất kỳ thư mục nào dẫn đến ổ cắm không thuộc sở hữu của www-data nhóm hoặc không có quyền đọc và thực thi trên thế giới, Nginx sẽ không thể truy cập vào socket. Thông thường, điều này có nghĩa là các tệp cấu hình có lỗi.

Nếu đường dẫn thư mục có quá hạn chế quyền hoặc quyền sở hữu, hãy xem /etc/systemd/system/uwsgi.service tập tin. Các ExecStartPre chỉ thị có trách nhiệm tạo ra /run/uwsgi và gán quyền sở hữu nhóm cho www-data nhóm. Nếu các lệnh ở đây không đúng, đường dẫn thư mục có thể quá hạn chế.

Nếu bản thân tập tin ổ cắm không thể tiếp cận với tiến trình Nginx, các thiết lập được xác định trong .ini tệp trong /etc/uwsgi/sites có thể không đúng. Kiểm tra các giá trị của chown-socketchmod-socket để đảm bảo rằng quy trình web được cấp quyền truy cập các tệp.

Gỡ rối thêm

Để khắc phục sự cố bổ sung, nhật ký có thể giúp thu hẹp nguyên nhân gốc. Kiểm tra từng người trong số họ lần lượt và tìm kiếm các thông báo cho biết khu vực có vấn đề.

Các nhật ký sau có thể hữu ích:

  • Kiểm tra các bản ghi quá trình Nginx bằng cách gõ: sudo journalctl -u nginx
  • Kiểm tra các bản ghi truy cập Nginx bằng cách gõ: sudo less /var/log/nginx/access.log
  • Kiểm tra các bản ghi lỗi Nginx bằng cách gõ: sudo less /var/log/nginx/error.log
  • Kiểm tra nhật ký ứng dụng uWSGI bằng cách gõ: sudo journalctl -u uwsgi

Khi bạn cập nhật cấu hình hoặc ứng dụng của mình, bạn có thể cần khởi động lại các quy trình để điều chỉnh các thay đổi của mình.

Nếu bạn cập nhật ứng dụng Django của mình, bạn có thể khởi động lại quá trình uWSGI để nhận các thay đổi bằng cách nhập:

sudo systemctl restart uwsgi

Nếu bạn thay đổi uwsgi tập tin dịch vụ systemd, tải lại daemon và khởi động lại quá trình bằng cách gõ:

sudo systemctl daemon-reload

sudo systemctl restart uwsgi

Nếu bạn thay đổi cấu hình khối máy chủ Nginx, hãy kiểm tra cấu hình và sau đó gõ Nginx bằng cách gõ:

sudo nginx -t && sudo systemctl restart nginx

Các lệnh này hữu ích khi chọn các thay đổi khi bạn điều chỉnh cấu hình của mình.

Phần kết luận

Trong hướng dẫn này, chúng tôi đã thiết lập hai dự án Django, mỗi dự án trong môi trường ảo của riêng họ. Chúng tôi đã 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 mỗi. Sau đó, chúng tôi thiết lập Nginx hoạt động như một proxy ngược để xử lý các kết nối máy khách và phục vụ dự án đúng tùy thuộc vào yêu cầu của máy khách.

Django giúp tạo các dự án và ứng dụng đơn giản bằng cách cung cấp nhiều phần phổ biến, 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 máy chủ duy nhất.