Thứ hai, 29/06/2020 | 00:00 GMT+7

Cách thiết lập Django với Postgres, Nginx và Gunicorn trên Ubuntu 20.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 20.04 để hỗ trợ và phục vụ các ứng dụng Django. Ta sẽ cài đặt database PostgreSQL thay vì sử dụng database SQLite mặc định. Ta sẽ cấu hình server ứng dụng Gunicorn để giao diện với các ứng dụng của ta . Sau đó, ta sẽ cài đặt Nginx để đảo ngược proxy cho Gunicorn, 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 phải có version server Ubuntu 20.04 mới với firewall cơ bản và 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 môi trường ảo. Việc cài đặt Django vào một môi trường dành riêng cho dự án của bạn 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.

Khi ta đã cài đặt và chạy database và ứng dụng của bạn , ta sẽ cài đặt và cấu hình server ứng dụng Gunicorn. Điều này sẽ đóng role như một giao diện cho ứng dụng của ta , dịch các yêu cầu của khách hàng từ các cuộc 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 Gunicorn để 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 các Gói từ Kho lưu trữ Ubuntu

Để bắt đầu quá trình, ta sẽ download và cài đặt tất cả các mục ta cần từ repository Ubuntu. Ta sẽ sử dụng pip quản lý gói Python để cài đặt các thành phần bổ sung sau một chút.

Ta cần cập nhật index gói apt local , sau đó download và cài đặt các gói. Các gói ta cài đặt phụ thuộc vào version Python nào mà dự án của bạn sẽ sử dụng.

Nếu bạn đang sử dụng Django với Python 3 , hãy nhập:

  • sudo apt update
  • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

Django 1.11 là bản phát hành cuối cùng của Django sẽ hỗ trợ Python 2. Nếu bạn đang bắt đầu các dự án mới, bạn nên chọn Python 3. Nếu bạn vẫn cần sử dụng Python 2 , hãy nhập:

  • sudo apt update
  • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

Điều này sẽ cài đặt pip , các file phát triển Python cần thiết để xây dựng Gunicorn sau này, hệ thống database Postgres và các thư viện cần thiết để tương tác với nó và web server Nginx.

Tạo Database và User PostgreSQL

Ta sẽ bắt đầu ngay lập tức và tạo database và user database cho ứng dụng Django của ta .

Theo mặc định, Postgres sử dụng một schemas xác thực được gọi là “xác thực ngang hàng” cho các kết nối local . Về cơ bản, điều này nghĩa là nếu tên user hệ điều hành của user trùng với tên user Postgres hợp lệ, user đó có thể đăng nhập mà không cần xác thực thêm.

Trong quá trình cài đặt Postgres, user hệ điều hành có tên là postgres đã được tạo để tương ứng với admin-user PostgreSQL của postgres . Ta cần sử dụng user này để thực hiện các việc quản trị. Ta có thể sử dụng sudo và nhập tên user với tùy chọn -u .

Đăng nhập vào một phiên Postgres tương tác bằng lệnh :

  • sudo -u postgres psql

Bạn sẽ nhận được dấu nhắc PostgreSQL để ta có thể cài đặt các yêu cầu của bạn .

Đầu tiên, tạo database cho dự án của bạn:

  • CREATE DATABASE myproject;

Lưu ý: Mọi câu lệnh Postgres phải kết thúc bằng dấu chấm phẩy, vì vậy hãy đảm bảo lệnh của bạn kết thúc bằng một câu lệnh nếu bạn đang gặp sự cố.

Tiếp theo, tạo một user database cho dự án của ta . Đảm bảo chọn một password an toàn:

  • CREATE USER myprojectuser WITH PASSWORD 'password';

Sau đó, ta sẽ sửa đổi một vài thông số kết nối cho user mà ta vừa tạo. Điều này sẽ tăng tốc hoạt động database để các giá trị chính xác không phải được truy vấn và đặt mỗi khi kết nối được cài đặt .

Ta đang đặt mã hóa mặc định thành UTF-8 , mà Django mong đợi. Ta cũng đang đặt schemas cách ly giao dịch mặc định thành “đọc được commit ”, ngăn chặn việc đọc từ các giao dịch không được commit . Cuối cùng, ta đang đặt múi giờ. Theo mặc định, các dự án Django của ta sẽ được đặt để sử dụng UTC . Đây là tất cả các khuyến nghị từ chính dự án Django :

  • ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
  • ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
  • ALTER ROLE myprojectuser SET timezone TO 'UTC';

Bây giờ, ta có thể cấp cho user mới quyền truy cập để quản lý database mới của ta :

  • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

Khi bạn hoàn tất, hãy thoát khỏi dấu nhắc PostgreSQL bằng lệnh :

  • \q

Postgres hiện đã được cài đặt để Django có thể kết nối và quản lý thông tin database của nó.

Tạo môi trường ảo Python cho dự án của bạn

Bây giờ ta đã có database của bạn , ta có thể bắt đầu chuẩn bị sẵn sàng phần còn lại của các yêu cầu dự án. Ta sẽ cài đặt các yêu cầu Python của bạn trong môi trường ảo để quản lý dễ dàng hơn.

Để làm điều này, trước tiên ta cần truy cập vào lệnh virtualenv . Ta có thể cài đặt cái này bằng pip .

Nếu bạn đang sử dụng Python 3 , hãy nâng cấp pip và cài đặt gói bằng lệnh :

  • sudo -H pip3 install --upgrade pip
  • sudo -H pip3 install virtualenv

Nếu bạn đang sử dụng Python 2 , hãy nâng cấp pip và cài đặt gói bằng lệnh :

  • sudo -H pip install --upgrade pip
  • sudo -H pip install virtualenv

Với virtualenv được cài đặt, ta có thể bắt đầu hình thành dự án của bạn . Tạo và di chuyển vào một folder nơi ta có thể giữ các file dự án của bạn :

  • mkdir ~/myprojectdir
  • cd ~/myprojectdir

Trong folder dự án, hãy tạo một môi trường ảo Python bằng lệnh :

  • virtualenv myprojectenv

Thao tác này sẽ tạo một folder có tên myprojectenv trong folder myprojectdir của bạn. Bên trong, nó sẽ cài đặt version local của Python và version local của pip . Ta có thể sử dụng điều này để cài đặt và cấu hình một môi trường Python riêng biệt cho dự án của bạn .

Trước khi cài đặt các yêu cầu Python của dự án, ta cần kích hoạt môi trường ảo. Bạn có thể thực hiện bằng cách gõ:

  • source myprojectenv/bin/activate

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 Python. Nó trông giống như sau : ( myprojectenv ) user @ host :~/ myprojectdir $ .

Với môi trường ảo của bạn đang hoạt động, hãy cài đặt Django, Gunicorn và bộ điều hợp psycopg2 PostgreSQL với version local của pip :

Lưu ý: Khi môi trường ảo được kích hoạt (khi dấu nhắc của bạn có (myprojectenv) đứng trước nó), hãy sử dụng pip thay vì pip3 , ngay cả khi bạn đang sử dụng Python 3. Bản sao của công cụ trong môi trường ảo luôn được đặt tên là pip , dù Python là gì version .

  • pip install django gunicorn psycopg2-binary

Đến đây bạn sẽ có tất cả phần mềm cần thiết để bắt đầu một dự án Django.

Tạo và cấu hình một dự án Django mới

Với các thành phần Python được cài đặt, ta có thể tạo các file dự án Django thực tế.

Tạo Dự án Django

Vì ta đã có folder dự án, ta sẽ yêu cầu Django cài đặt các file ở đây. Nó sẽ tạo một folder cấp hai với mã thực, điều này bình thường và đặt một tập lệnh quản lý vào folder này. Key của điều này là ta đang xác định folder một cách rõ ràng thay vì cho phép Django đưa ra quyết định liên quan đến folder hiện tại của ta :

  • django-admin.py startproject myproject ~/myprojectdir

Đến đây, folder dự án của bạn ( ~/ myprojectdir trong trường hợp của ta ) sẽ có nội dung sau:

  • ~/myprojectdir/manage.py : Một tập lệnh quản lý dự án Django.
  • ~/myprojectdir/myproject/ : Gói dự án Django. Điều này phải chứa các file __init__.py , settings.py , urls.py , asgi.pywsgi.py
  • ~/myprojectdir/myprojectenv/ : Thư mục môi trường ảo mà ta đã tạo trước đó.

Điều chỉnh cài đặt dự án

Điều đầu tiên ta nên làm với các file dự án mới tạo của bạn là điều chỉnh cài đặt. Mở file cài đặt trong editor của bạn:

  • nano ~/myprojectdir/myproject/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ỉ của server hoặc domain đượ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:

Lưu ý: Đảm bảo bao gồm localhost là một trong các tùy chọn vì ta sẽ cung cấp các kết nối proxy thông qua version Nginx local .

~ / myprojectdir / myproject / 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', . . ., 'localhost'] 

Tiếp theo, tìm phần cấu hình quyền truy cập database . Nó sẽ bắt đầu với DATABASES . Cấu hình trong file dành cho database SQLite. Ta đã tạo database PostgreSQL cho dự án của bạn , vì vậy ta cần điều chỉnh cài đặt.

Thay đổi cài đặt với thông tin database PostgreSQL của bạn. Ta yêu cầu Django sử dụng bộ điều hợp psycopg2 mà ta đã cài đặt bằng pip . Ta cần cung cấp tên database , tên user database , password của user database và sau đó chỉ định rằng database được đặt trên máy tính local . Bạn có thể để cài đặt PORT dưới dạng một chuỗi trống:

~ / myprojectdir / myproject / settings.py
. . .  DATABASES = {     'default': {         'ENGINE': 'django.db.backends.postgresql_psycopg2',         'NAME': 'myproject',         'USER': 'myprojectuser',         'PASSWORD': 'password',         'HOST': 'localhost',         'PORT': '',     } }  . . . 

Tiếp theo, di chuyển xuống cuối file và thêm cài đặt cho biết vị trí các file tĩnh sẽ được đặt. Điều này là cần thiết để Nginx có thể xử lý các yêu cầu cho các mục này. Dòng sau yêu cầu Django đặt chúng vào một folder được gọi là static trong folder dự án cơ sở:

~ / myprojectdir / myproject / settings.py
. . .  STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/') 

Lưu file khi bạn hoàn tất.

Hoàn thành cài đặt dự án ban đầu

Bây giờ, ta có thể di chuyển schemas database ban đầu sang database PostgreSQL của ta bằng cách sử dụng tập lệnh quản lý:

  • ~/myprojectdir/manage.py makemigrations
  • ~/myprojectdir/manage.py migrate

Tạo admin-user cho dự án bằng lệnh :

  • ~/myprojectdir/manage.py createsuperuser

Bạn sẽ phải chọn tên user , cung cấp địa chỉ email, chọn và xác nhận password .

Ta có thể thu thập tất cả nội dung tĩnh vào vị trí folder mà ta đã cấu hình bằng lệnh :

  • ~/myprojectdir/manage.py collectstatic

Bạn sẽ phải xác nhận hoạt động. Các file tĩnh sau đó sẽ được đặt trong một folder được gọi là static trong folder dự án của bạn.

Nếu bạn đã làm theo hướng dẫn cài đặt server ban đầu, bạn phải có firewall UFW bảo vệ server của bạn . Để kiểm tra server phát triển, ta sẽ phải cho phép truy cập vào cổng mà ta sẽ sử dụng.

Tạo một ngoại lệ cho cổng 8000 bằng lệnh :

  • sudo ufw allow 8000

Cuối cùng, bạn có thể kiểm tra dự án của ta bằng cách khởi động server phát triển Django bằng lệnh sau:

  • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

Trong trình duyệt web , hãy truy cập vào domain hoặc địa chỉ IP của server , sau đó là :8000 :

http://server_domain_or_IP:8000 

Bạn sẽ nhận được trang index Django mặc định:

Trang index  Django

Nếu bạn thêm /admin vào cuối URL trong thanh địa chỉ, bạn sẽ được yêu cầu nhập tên user và password quản trị mà bạn đã tạo bằng lệnh createsuperuser :

Đăng nhập quản trị Django

Sau khi xác thực, bạn có thể truy cập giao diện quản trị Django mặc định:

Giao diện quản trị Django

Khi bạn khám phá xong, hãy nhấn CTRL-C trong cửa sổ terminal để tắt server phát triển.

Kiểm tra khả năng phục vụ dự án của Gunicorn

Điều cuối cùng ta muốn làm trước khi rời khỏi môi trường ảo của bạn là kiểm tra Gunicorn đảm bảo rằng nó có thể phục vụ ứng dụng. Ta có thể làm điều này bằng lệnh folder dự án của bạn và sử dụng gunicorn để tải module WSGI của dự án:

  • cd ~/myprojectdir
  • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

Thao tác này sẽ khởi động Gunicorn trên cùng giao diện mà server phát triển Django đang chạy. Bạn có thể quay lại và kiểm tra lại ứng dụng.

Lưu ý: Giao diện quản trị sẽ không có bất kỳ kiểu nào được áp dụng vì Gunicorn không biết cách tìm nội dung CSS tĩnh chịu trách nhiệm cho việc này.

Ta đã chuyển cho Gunicorn một module bằng cách chỉ định đường dẫn folder tương đối đến file wsgi.py của Django, là điểm vào ứng dụng của ta , sử dụng cú pháp module của Python. Bên trong file này, một chức năng được gọi là application được định nghĩa, được sử dụng để giao tiếp với ứng dụng. Để tìm hiểu thêm về đặc điểm kỹ thuật WSGI, hãy nhấp vào đây .

Khi bạn kiểm tra xong, nhấn CTRL-C trong cửa sổ dòng lệnh để dừng Gunicorn.

Bây giờ ta đã hoàn tất việc cấu hình ứng dụng Django của bạn . Ta có thể thoát khỏi môi trường ảo của bạn bằng lệnh :

  • deactivate

Chỉ báo môi trường ảo trong dấu nhắc của bạn sẽ bị xóa.

Tạo socket systemd và file dịch vụ cho Gunicorn

Ta đã kiểm tra rằng Gunicorn có thể tương tác với ứng dụng Django của ta , nhưng ta nên triển khai một cách khởi động và dừng server ứng dụng mạnh mẽ hơn. Để thực hiện điều này, ta sẽ tạo dịch vụ systemd và các file socket.

Ổ cắm Gunicorn sẽ được tạo khi khởi động và sẽ lắng nghe các kết nối. Khi kết nối xảy ra, systemd sẽ tự động bắt đầu quy trình Gunicorn để xử lý kết nối.

Bắt đầu bằng cách tạo và mở file socket systemd cho Gunicorn với các quyền sudo :

  • sudo nano /etc/systemd/system/gunicorn.socket

Bên trong, ta sẽ tạo phần [Unit] để mô tả socket , phần [Socket] để xác định vị trí socket và phần [Install] đảm bảo socket được tạo vào đúng thời điểm:

/etc/systemd/system/gunicorn.socket
[Unit] Description=gunicorn socket  [Socket] ListenStream=/run/gunicorn.sock  [Install] WantedBy=sockets.target 

Lưu file khi bạn hoàn tất.

Tiếp theo, tạo và mở file dịch vụ systemd cho Gunicorn với các quyền sudo trong editor của bạn. Tên file dịch vụ phải trùng với tên file socket ngoại trừ phần mở rộng:

  • sudo nano /etc/systemd/system/gunicorn.service

Bắt đầu với phần [Unit] , được sử dụng để chỉ định metadata và phần phụ thuộc. Ta sẽ đặt mô tả về dịch vụ của bạn ở đây và yêu cầu hệ thống init chỉ bắt đầu điều này sau khi đã đạt được mục tiêu mạng. Bởi vì dịch vụ của ta dựa vào socket từ file socket, ta cần bao gồm chỉ thị Requires để chỉ ra mối quan hệ đó:

/etc/systemd/system/gunicorn.service
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target 

Tiếp theo, ta sẽ mở phần [Service] . Ta sẽ chỉ định user và group mà ta muốn xử lý để chạy. Ta sẽ cấp cho account regular user quyền sở hữu quy trình vì nó sở hữu tất cả các file có liên quan. Ta sẽ cấp quyền sở hữu group cho www-data group để Nginx có thể giao tiếp dễ dàng với Gunicorn.

Sau đó, ta sẽ vạch ra folder làm việc và chỉ định lệnh sử dụng để bắt đầu dịch vụ. Trong trường hợp này, ta sẽ phải chỉ định đường dẫn đầy đủ đến file thực thi Gunicorn, được cài đặt trong môi trường ảo của ta . Ta sẽ liên kết quy trình với socket Unix mà ta đã tạo trong folder /run để quy trình có thể giao tiếp với Nginx. Ta ghi lại tất cả dữ liệu vào kết quả chuẩn để quá trình journald có thể thu thập log Gunicorn. Ta cũng có thể chỉ định bất kỳ chỉnh sửa Gunicorn tùy chọn nào tại đây. Ví dụ: ta đã chỉ định 3 quy trình công nhân trong trường hợp này:

/etc/systemd/system/gunicorn.service
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target  [Service] User=sammy Group=www-data WorkingDirectory=/home/sammy/myprojectdir ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \           --access-logfile - \           --workers 3 \           --bind unix:/run/gunicorn.sock \           myproject.wsgi:application 

Cuối cùng, ta sẽ thêm phần [Install] . Điều này sẽ cho systemd biết những gì để liên kết dịch vụ này nếu ta cho phép nó khởi động khi server khởi động . Ta muốn dịch vụ này bắt đầu khi hệ thống nhiều regular user được cài đặt và chạy:

/etc/systemd/system/gunicorn.service
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target  [Service] User=sammy Group=www-data WorkingDirectory=/home/sammy/myprojectdir ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \           --access-logfile - \           --workers 3 \           --bind unix:/run/gunicorn.sock \           myproject.wsgi:application  [Install] WantedBy=multi-user.target 

Như vậy, file dịch vụ systemd của ta đã hoàn tất. Lưu và đóng nó ngay bây giờ.

Bây giờ ta có thể khởi động và kích hoạt socket Gunicorn. Thao tác này sẽ tạo file socket tại /run/gunicorn.sock ngay bây giờ và khi khởi động. Khi kết nối được thực hiện với socket đó, systemd sẽ tự động khởi động gunicorn.service để xử lý nó:

  • sudo systemctl start gunicorn.socket
  • sudo systemctl enable gunicorn.socket

Ta có thể xác nhận thao tác đã thành công bằng cách kiểm tra file socket.

Kiểm tra file socket Gunicorn

Kiểm tra trạng thái của quá trình để tìm hiểu xem nó có thể bắt đầu hay không:

  • sudo systemctl status gunicorn.socket

Bạn sẽ nhận được một kết quả như thế này:

Output
● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

Tiếp theo, kiểm tra sự tồn tại của file gunicorn.sock trong folder /run :

  • file /run/gunicorn.sock
Output
/run/gunicorn.sock: socket

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 gunicorn.sock trong folder , thì đó là dấu hiệu cho thấy socket Gunicorn không được tạo đúng cách. Kiểm tra log của socket Gunicorn bằng lệnh :

  • sudo journalctl -u gunicorn.socket

Hãy xem lại file /etc/systemd/system/gunicorn.socket của bạn để khắc phục mọi sự cố trước khi tiếp tục.

Kiểm tra kích hoạt socket

Hiện tại, nếu bạn chỉ khởi động đơn vị gunicorn.socket , gunicorn.service sẽ chưa hoạt động vì socket chưa nhận được bất kỳ kết nối nào. Bạn có thể kiểm tra bằng lệnh :

  • sudo systemctl status gunicorn
Output
● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

Để kiểm tra cơ chế kích hoạt socket , ta có thể gửi kết nối đến socket thông qua curl bằng lệnh :

  • curl --unix-socket /run/gunicorn.sock localhost

Bạn sẽ nhận được kết quả HTML từ ứng dụng của bạn trong terminal . Điều này cho thấy rằng Gunicorn đã được khởi động và có thể phân phát ứng dụng Django của bạn. Bạn có thể xác minh dịch vụ Gunicorn đang chạy bằng lệnh :

  • sudo systemctl status gunicorn
Output
● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

Nếu kết quả từ curl hoặc kết quả của systemctl status cho biết sự cố đã xảy ra, hãy kiểm tra log để biết thêm chi tiết:

  • sudo journalctl -u gunicorn

Kiểm tra file /etc/systemd/system/gunicorn.service của bạn xem có sự cố không. Nếu bạn thực hiện thay đổi đối với file /etc/systemd/system/gunicorn.service , hãy reload daemon để đọc lại định nghĩa dịch vụ và khởi động lại quy trình Gunicorn bằng lệnh :

  • sudo systemctl daemon-reload
  • sudo systemctl restart gunicorn

Đảm bảo rằng bạn khắc phục sự cố ở trên trước khi tiếp tục.

Cấu hình Nginx thành Proxy Pass tới Gunicorn

Bây giờ Gunicorn đã được cài đặt , ta cần cấu hình Nginx để chuyển lưu lượng truy cập vào quy trình.

Bắt đầu bằng cách tạo và mở một khối server mới trong folder sites-available của Nginx:

  • sudo nano /etc/nginx/sites-available/myproject

Bên trong, mở một khối server mới. Ta sẽ bắt đầu bằng cách chỉ định rằng khối này sẽ lắng nghe trên cổng thông thường 80 và nó sẽ phản hồi với domain hoặc địa chỉ IP của server của ta :

/ etc / nginx / sites-available / myproject
server {     listen 80;     server_name server_domain_or_IP; } 

Tiếp theo, ta sẽ yêu cầu Nginx bỏ qua bất kỳ vấn đề nào với việc tìm biểu tượng yêu thích. Ta cũng sẽ cho nó biết nơi tìm các tài sản tĩnh mà ta đã thu thập trong folder ~/ myprojectdir /static của ta . Tất cả các file này đều có tiền tố URI tiêu chuẩn là “/ static”, vì vậy ta có thể tạo khối vị trí để trùng với các yêu cầu đó:

/ etc / nginx / sites-available / myproject
server {     listen 80;     server_name server_domain_or_IP;      location = /favicon.ico { access_log off; log_not_found off; }     location /static/ {         root /home/sammy/myprojectdir;     } } 

Cuối cùng, ta sẽ tạo khối location / {} để trùng với tất cả các yêu cầu khác. Bên trong vị trí này, ta sẽ bao gồm file proxy_params tiêu chuẩn có trong cài đặt Nginx và sau đó ta sẽ chuyển lưu lượng truy cập trực tiếp đến socket Gunicorn:

/ etc / nginx / sites-available / myproject
server {     listen 80;     server_name server_domain_or_IP;      location = /favicon.ico { access_log off; log_not_found off; }     location /static/ {         root /home/sammy/myprojectdir;     }      location / {         include proxy_params;         proxy_pass http://unix:/run/gunicorn.sock;     } } 

Lưu file khi bạn hoàn tất. Bây giờ, ta có thể kích hoạt file bằng cách liên kết file với folder sites-enabled :

  • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

Kiểm tra cấu hình Nginx của bạn để tìm lỗi cú pháp bằng lệnh :

  • sudo nginx -t

Nếu không có lỗi nào được báo cáo, hãy tiếp tục và khởi động lại Nginx bằng lệnh :

  • sudo systemctl restart nginx

Cuối cùng, ta cần mở firewall của bạn để lưu lượng truy cập bình thường trên cổng 80. Vì ta không cần truy cập vào server phát triển nữa, ta cũng có thể loại bỏ luật để mở cổng 8000:

  • sudo ufw delete allow 8000
  • sudo ufw allow 'Nginx Full'

Đến đây bạn có thể truy cập domain hoặc địa chỉ IP của server để xem ứng dụng của bạn .

Lưu ý: Sau khi cấu hình Nginx, bước tiếp theo phải đảm bảo lưu lượng truy cập đến 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 20.04. Làm theo quy trình bằng cách sử dụng khối server Nginx mà ta đã tạo trong hướng dẫn này.

Khắc phục sự cố Nginx và Gunicorn

Nếu bước cuối cùng này không hiển thị ứ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/ myproject file để trỏ đến địa chỉ hoặc domain tên IP của server .

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 được trang Nginx mặc định, thì đó là dấu hiệu cho thấy Nginx không thể đối sánh yêu cầu với khối server một cách rõ ràng, vì vậy nó 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ẽ nhận được 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ể nhận được thông báo sau:

kết nối () với unix: /run/gunicorn.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 gunicorn.sock tại vị trí đã cho. Bạn nên so sánh vị trí proxy_pass được xác định trong proxy_pass /etc/nginx/sites-available/myproject với vị trí thực của file gunicorn.sock được tạo bởi đơn vị gunicorn.socket systemd.

Nếu bạn không thể tìm thấy file gunicorn.sock trong folder /run , điều đó thường nghĩa là file socket systemd không thể tạo nó. Quay lại phần kiểm tra file socket Gunicorn để thực hiện các bước khắc phục sự cố cho Gunicorn.

connect () với unix: /run/gunicorn.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 Gunicorn do các vấn đề về quyền. Điều này có thể xảy ra khi quy trình được tuân theo bằng cách sử dụng user root thay vì user sudo . Trong khi systemd có thể tạo file socket Gunicorn, Nginx không thể truy cập vào 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 gunicorn.sock . Ta có thể xem xét 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 -l /run/gunicorn.sock
Output
f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.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, file socket và 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ì --- ). 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 có quyền đọc và thực thi thế giới, Nginx sẽ không thể truy cập vào socket mà không cho phép quyền đọc và thực thi thế giới hoặc đảm bảo quyền sở hữu group được trao cho một group mà Nginx là một phần của.

Django đang hiển thị: "không thể kết nối với server : Kết nối bị từ chối"

Một thông báo mà bạn có thể nhận được từ Django khi cố gắng truy cập các phần của ứng dụng trong trình duyệt web là:

OperationalError at /admin/login/ could not connect to server: Connection refused     Is the server running on host "localhost" (127.0.0.1) and accepting     TCP/IP connections on port 5432? 

Điều này cho biết Django không thể kết nối với database Postgres. Đảm bảo rằng version Postgres đang chạy bằng lệnh :

  • sudo systemctl status postgresql

Nếu không, bạn có thể khởi động nó và cho phép nó tự động khởi động khi server khởi động (nếu nó chưa được cấu hình để thực hiện ) bằng lệnh :

  • sudo systemctl start postgresql
  • sudo systemctl enable postgresql

Nếu bạn vẫn gặp sự cố, hãy đảm bảo cài đặt database được xác định trong file ~/myprojectdir/myproject/settings.py là chính xác.

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 Gunicorn bằng lệnh : sudo journalctl -u gunicorn
  • Kiểm tra log socket Gunicorn bằng lệnh : sudo journalctl -u gunicorn.socket

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 Gunicorn để nhận các thay đổi bằng lệnh :

  • sudo systemctl restart gunicorn

Nếu bạn thay đổi file socket hoặc dịch vụ Gunicorn, hãy reload daemon và khởi động lại quá trình bằng lệnh :

  • sudo systemctl daemon-reload
  • sudo systemctl restart gunicorn.socket gunicorn.service

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 một dự án Django trong môi trường ảo của riêng nó. Ta đã cấu hình Gunicorn để dịch các yêu cầu của khách hàng để Django có thể xử lý chúng. 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.


Tags:

Các tin liên quan

Cách thiết lập Nginx với Hỗ trợ HTTP / 2 trên Ubuntu 18.04
2020-06-09
Cách cung cấp các ứng dụng Flask với uWSGI và Nginx trên Ubuntu 20.04
2020-05-26
Cách cung cấp các ứng dụng Flask với uWSGI và Nginx trên Ubuntu 18.04
2020-05-21
Cách bảo mật Nginx bằng Let's Encrypt trên Ubuntu 20.04
2020-05-20
Cách cung cấp các ứng dụng Flask với Gunicorn và Nginx trên Ubuntu 20.04
2020-05-20
Cách cài đặt và cấu hình Laravel với Nginx trên Ubuntu 20.04
2020-05-19
Cách cài đặt Nginx trên Ubuntu 18.04
2020-05-06
Cách cài đặt Nginx trên Ubuntu 20.04 [Quickstart]
2020-05-04
Cách cài đặt Nginx trên Ubuntu 20.04
2020-04-24
Cách tối ưu hóa cấu hình Nginx
2020-03-26