Django là một framework web mạnh mẽ, giúp lập trình viên phát triển nhanh chóng các ứng dụng và website bằng Python. Mặc dù Django cung cấp một máy chủ phát triển tích hợp để thử nghiệm mã nguồn cục bộ, nhưng để triển khai trong môi trường sản xuất, bạn cần một giải pháp máy chủ web an toàn và hiệu suất cao hơn.
Trong hướng dẫn này, bạn sẽ thiết lập và cấu hình một môi trường sản xuất hoàn chỉnh trên Ubuntu 22.04 (hoặc các phiên bản Ubuntu được hỗ trợ khác) để triển khai ứng dụng Django. Trước tiên, bạn sẽ sử dụng PostgreSQL làm hệ quản trị cơ sở dữ liệu thay thế SQLite mặc định, giúp nâng cao khả năng mở rộng và quản lý dữ liệu. Tiếp theo, bạn sẽ cài đặt và cấu hình Gunicorn làm máy chủ ứng dụng để xử lý các yêu cầu HTTP và giao tiếp với ứng dụng Django. Cuối cùng, bạn sẽ triển khai Nginx làm reverse proxy cho Gunicorn, tận dụng khả năng xử lý kết nối mạnh mẽ và các tính năng bảo mật của Nginx nhằm tối ưu hóa hiệu suất và bảo vệ ứng dụng của bạn.
Bên cạnh đó, bạn sẽ cài đặt Django trong một môi trường ảo (virtual environment), đảm bảo tính độc lập cho từng dự án và giúp quản lý dễ dàng các dependencies. Khi cơ sở dữ liệu và ứng dụng đã hoạt động ổn định, bạn sẽ hoàn thiện hệ thống bằng cách tích hợp Gunicorn và Nginx để tối ưu hóa quá trình xử lý yêu cầu.
Với cấu hình này, bạn sẽ có một hệ thống vững chắc để triển khai ứng dụng Django trên môi trường sản xuất, đảm bảo hiệu suất cao, tính bảo mật mạnh mẽ và khả năng mở rộng linh hoạt.
Điều kiện tiên quyết
Nếu bạn đang sử dụng Ubuntu phiên bản 16.04 trở xuống, chúng tôi khuyên bạn nên nâng cấp lên phiên bản mới hơn, vì Ubuntu đã ngừng hỗ trợ các phiên bản này. Bộ sưu tập hướng dẫn này sẽ hỗ trợ bạn trong việc nâng cấp Ubuntu.
Để hoàn thành hướng dẫn này, bạn cần:
- Một máy chủ chạy Ubuntu,
- Một người dùng không phải root (non-root) có quyền
sudo
, - Một tường lửa đã được kích hoạt.
Để biết cách thiết lập, hãy chọn phiên bản Ubuntu của bạn trong danh sách này và làm theo hướng dẫn “Initial Server Setup Guide”.
Bước 1 – Cài đặt các gói từ kho Ubuntu
Đầu tiên, bạn sẽ tải và cài đặt tất cả thành phần cần thiết từ kho Ubuntu. Sau đó, bạn sẽ dùng pip (trình quản lý gói Python) để cài thêm các thành phần khác.
Trước hết, hãy cập nhật chỉ mục gói cục bộ apt
và cài đặt các gói cần thiết. Những gói này phụ thuộc vào phiên bản Python mà dự án của bạn sử dụng.
Nếu bạn sử dụng Django với Python 3, hãy chạy:
sudo apt update sudo apt install python3-venv python3-dev libpq-dev postgresql postgresql-contrib nginx curl
Lệnh này sẽ cài công cụ tạo môi trường ảo (virtual environment) cho các dự án Python, các tệp phát triển Python (cần thiết để biên dịch Gunicorn sau này), hệ thống cơ sở dữ liệu Postgres cùng thư viện tương tác với nó, và máy chủ web Nginx.
Bước 2 – Tạo cơ sở dữ liệu và người dùng PostgreSQL
Bây giờ, bạn có thể tạo ngay một cơ sở dữ liệu (database) và một người dùng (user) cho ứng dụng Django của mình.
Mặc định, Postgres dùng phương thức xác thực “peer authentication” cho kết nối cục bộ. Nói đơn giản, nếu tên người dùng hệ điều hành trùng khớp với một người dùng hợp lệ của Postgres, thì người dùng đó có thể đăng nhập mà không cần thêm xác thực.
Trong quá trình cài đặt Postgres, một người dùng hệ điều hành tên postgres
đã được tạo, ứng với người dùng quản trị postgres
trong PostgreSQL. Bạn cần dùng người dùng này để thực hiện tác vụ quản trị. Bạn có thể dùng sudo
và truyền tham số -u
để xác định tên người dùng.
Đăng nhập vào phiên làm việc tương tác của Postgres bằng lệnh:
sudo -u postgres psql
Bạn sẽ thấy dấu nhắc lệnh PostgreSQL, nơi bạn có thể thiết lập các yêu cầu của mình.
Trước tiên, tạo một cơ sở dữ liệu cho dự án:
CREATE DATABASE myproject;
Tiếp theo, tạo một người dùng cơ sở dữ liệu cho dự án. Hãy chọn mật khẩu an toàn:
CREATE USER myprojectuser WITH PASSWORD 'password';
Sau đó, bạn sẽ điều chỉnh một số tham số kết nối cho người dùng vừa tạo. Điều này giúp tăng tốc độ hoạt động với cơ sở dữ liệu, vì các giá trị đúng không cần phải truy vấn và thiết lập mỗi khi khởi tạo kết nối.
Bạn sẽ đặt mã hóa ký tự mặc định là UTF-8 (Django mong đợi điều này). Bạn cũng thiết lập chế độ cách ly giao dịch mặc định là “read committed” (chặn đọc từ các giao dịch chưa commit). Cuối cùng, bạn đặt múi giờ (timezone). Mặc định, các dự án Django sử dụng UTC. Đây đều là khuyến khích chính thức từ 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ờ, bạn có thể cấp quyền cho người dùng mới để quản trị cơ sở dữ liệu mới:
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
Khi hoàn tất, thoát khỏi phiên làm việc PostgreSQL bằng cách gõ:
\q
Postgres giờ đã sẵn sàng để Django kết nối và quản lý thông tin trong cơ sở dữ liệu.
Bước 3 – Tạo môi trường ảo Python cho dự án của bạn
Giờ bạn đã có một cơ sở dữ liệu, bạn có thể bắt đầu cài đặt các thành phần còn lại cho dự án. Bạn sẽ cài các gói Python trong một virtual environment để dễ quản lý.
Trước tiên, tạo một thư mục và chuyển vào đó để lưu trữ tệp dự án:
mkdir ~/myprojectdir cd ~/myprojectdir
Trong thư mục dự án, tạo một môi trường ảo Python bằng lệnh:
python3 -m venv myprojectenv
Lệnh này sẽ tạo một thư mục myprojectenv
bên trong ~/myprojectdir
. Thư mục này chứa phiên bản Python cục bộ và pip cục bộ để quản lý gói. Bạn có thể dùng cấu trúc môi trường ảo này để cài đặt và cấu hình một môi trường Python độc lập cho bất kỳ dự án nào.
Trước khi cài đặt các yêu cầu Python cho dự án, bạn cần kích hoạt môi trường ảo. Thực hiện bằng lệnh:
source myprojectenv/bin/activate
Lúc này, dấu nhắc lệnh sẽ thay đổi, báo hiệu bạn đang hoạt động trong môi trường ảo Python, ví dụ:
Với môi trường ảo đang bật, hãy cài Django, Gunicorn, và bộ kết nối psycopg2 (PostgreSQL) bằng pip cục bộ:
Lưu ý: Khi môi trường ảo đã được kích hoạt (dấu nhắc lệnh có
(myprojectenv)
), hãy dùngpip
thay vìpip3
, ngay cả khi bạn dùng Python 3. Bản pip trong môi trường ảo luôn mang tênpip
, bất kể phiên bản Python.
pip install django gunicorn psycopg2-binary
Bạn đã có đầy đủ các phần mềm cần để bắt đầu dự án Django.
Bước 4 – Tạo và cấu hình dự án Django mới
Sau khi cài xong các thành phần Python, bạn có thể tạo các tệp dự án Django thực tế.
Vì bạn đã có một thư mục dự án, bạn sẽ bảo Django cài đặt các tệp vào đây. Django sẽ tạo một thư mục con (chứa mã nguồn chính), và đặt một script quản lý ở ngay thư mục này. Mấu chốt là bạn chỉ rõ thư mục thay vì để Django tự động quyết định dựa trên thư mục hiện tại:
Lúc này, thư mục dự án ~/myprojectdir
sẽ có những nội dung sau:
~/myprojectdir/manage.py
: Tệp script quản lý dự án Django.~/myprojectdir/myproject/
: Gói (package) dự án Django. Thư mục này chứa các tệp__init__.py
,settings.py
,urls.py
,asgi.py
,wsgi.py
.~/myprojectdir/myprojectenv/
: Thư mục môi trường ảo bạn vừa tạo.
Việc đầu tiên với các tệp dự án mới tạo là điều chỉnh settings. Mở tệp cấu hình:
django-admin startproject myproject ~/myprojectdir
Tìm dòng ALLOWED_HOSTS
. Dòng này định nghĩa danh sách địa chỉ IP hoặc tên miền được phép kết nối đến Django. Mọi yêu cầu đến với Host
header không nằm trong danh sách này sẽ bị từ chối. Django yêu cầu thiết lập danh sách này để ngăn chặn một số lỗ hổng bảo mật nhất định.
Trong ngoặc vuông, hãy liệt kê các địa chỉ IP hoặc tên miền gắn với máy chủ Django. Mỗi phần tử nên nằm trong dấu nháy, cách nhau bằng dấu phẩy. Nếu bạn muốn cho phép toàn bộ tên miền và các subdomain, hãy thêm dấu chấm .
ở đầu tên miền. Dưới đây là ví dụ mô tả:
Lưu ý: Nhớ thêm
localhost
vì bạn sẽ reverse proxy từ Nginx cục bộ.
~/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', . . ., 'localhos
Kế tiếp, tìm đến phần cấu hình cơ sở dữ liệu (bắt đầu với DATABASES
). Mặc định, cấu hình này dành cho SQLite. Bạn đã tạo một cơ sở dữ liệu PostgreSQL, vì thế bạn cần chỉnh lại cài đặt.
Hãy dùng trình điều khiển psycopg2
mà bạn đã cài qua pip. Bạn cần cung cấp tên cơ sở dữ liệu, tên người dùng, mật khẩu người dùng, rồi chỉ định rằng cơ sở dữ liệu nằm trên máy cục bộ (localhost
). Bạn có thể để trống PORT
:
~/myprojectdir/myproject/settings.py . . . DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'myproject', 'USER': 'myprojectuser', 'PASSWORD': 'password', 'HOST': 'localhost', 'PORT': '', } } . . .
Tiếp theo, cuộn xuống cuối tệp và thêm cấu hình nơi đặt static files. Điều này cần thiết để Nginx có thể xử lý yêu cầu các tệp tĩnh. Dòng sau báo Django đặt chúng vào thư mục static
trong thư mục gốc dự án:
~/myprojectdir/myproject/settings.py . . . STATIC_URL = 'static/' # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' import os STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Lưu và đóng tệp khi hoàn tất.
Bước 5 – Hoàn tất thiết lập ban đầu cho dự án
Bây giờ, bạn có thể chạy lệnh migrate để áp dụng schema cơ sở dữ liệu ban đầu lên PostgreSQL:
~/myprojectdir/manage.py makemigrations ~/myprojectdir/manage.py migrate
Tạo người dùng quản trị (admin) cho dự án:
~/myprojectdir/manage.py createsuperuser
Bạn sẽ phải nhập tên người dùng, email, mật khẩu và xác nhận mật khẩu.
Bạn cũng có thể gom tất cả nội dung tĩnh (static) vào thư mục static
đã cấu hình bằng lệnh:
~/myprojectdir/manage.py collectstatic
Bạn cần xác nhận thao tác. Các tệp tĩnh sẽ được đưa vào thư mục static
trong thư mục dự án.
Nếu bạn làm theo hướng dẫn “initial server setup,” bạn có thể đã bật UFW firewall để bảo vệ máy chủ. Để thử nghiệm máy chủ phát triển (development server), bạn cần cho phép truy cập cổng 8000:
sudo ufw allow 8000
Cuối cùng, hãy kiểm tra dự án bằng cách khởi chạy máy chủ phát triển Django:
~/myprojectdir/manage.py runserver 0.0.0.0:8000
Mở trình duyệt và truy cập địa chỉ IP hoặc tên miền máy chủ kèm :8000
:
http://server_domain_or_IP:8000
Bạn sẽ thấy trang mặc định của Django:
Nếu bạn thêm /admin
vào cuối URL, bạn sẽ được yêu cầu đăng nhập bằng tài khoản admin đã tạo với createsuperuser
:
Sau khi xác thực, bạn có thể truy cập giao diện quản trị mặc định của Django:
Khi thử nghiệm xong, nhấn CTRL-C trong cửa sổ terminal để dừng máy chủ phát triển.
Bước 6 – Kiểm tra khả năng phục vụ dự án của Gunicorn
Trước khi thoát khỏi môi trường ảo, bạn cần kiểm tra Gunicorn có thể phục vụ ứng dụng hay không. Chuyển vào thư mục dự án và dùng Gunicorn để tải module WSGI của dự án:
cd ~/myprojectdir gunicorn --bind 0.0.0.0:8000 myproject.wsgi
Lệnh này khởi chạy Gunicorn trên cùng cổng mà máy chủ phát triển Django đang dùng. Bạn có thể kiểm tra lại ứng dụng trong trình duyệt.
Lưu ý: Giao diện quản trị sẽ không có CSS vì Gunicorn không biết cách tìm các tệp CSS tĩnh.
Bạn đã truyền cho Gunicorn một module bằng cách chỉ định đường dẫn đến tệp wsgi.py
của Django (điểm vào ứng dụng) theo cú pháp module của Python. Bên trong tệp này, hàm application
được định nghĩa để giao tiếp với ứng dụng.
Khi kiểm tra xong, nhấn CTRL-C để dừng Gunicorn.
Lúc này, bạn đã cấu hình xong ứng dụng Django. Bạn có thể thoát khỏi môi trường ảo:
deactivate
Dấu nhắc lệnh sẽ trở lại bình thường (không còn (myprojectenv)
).
Bước 7 – Tạo các tệp Socket và Service của Gunicorn trên systemd
Bạn đã thử nghiệm Gunicorn tương tác với ứng dụng Django, nhưng cần một cách khởi động/dừng dịch vụ mạnh mẽ hơn. Bạn sẽ tạo tệp service và socket cho systemd.
Socket của Gunicorn sẽ được tạo khi khởi động máy (boot) và lắng nghe kết nối. Khi có kết nối, systemd sẽ tự động khởi chạy Gunicorn để xử lý.
Bắt đầu bằng cách tạo tệp socket của Gunicorn với quyền sudo
:
sudo nano /etc/systemd/system/gunicorn.socket
Bên trong, 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 đúng lúc:
etc/systemd/system/gunicorn.socket [Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target
Lưu và đóng tệp.
Tiếp theo, tạo và mở tệp service cho Gunicorn (với quyền sudo
). Tên tệp dịch vụ nên trùng với tên socket, chỉ khác phần mở rộng:
sudo nano /etc/systemd/system/gunicorn.service
Bắt đầu với phần [Unit]
, chứa metadata và các phụ thuộc. Đưa mô tả cho dịch vụ, yêu cầu chỉ khởi động sau khi mạng (network.target
) đã sẵn sàng. Vì dịch vụ phụ thuộc vào socket, bạn cần Requires=gunicorn.socket
:
/etc/systemd/system/gunicorn.service [Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target
Kế tiếp, mở phần [Service]
. Chỉ định user và group mà tiến trình chạy dưới quyền đó. Ở đây, bạn để user là người dùng thường (sở hữu các tệp dự án), group là www-data
để Nginx giao tiếp dễ dàng với Gunicorn.
Sau đó, bạn chỉ định thư mục làm việc (working directory) và câu lệnh khởi chạy dịch vụ (đường dẫn đầy đủ tới Gunicorn trong môi trường ảo). Bạn bind tiến trình đến Unix socket /run/gunicorn.sock
để Nginx có thể kết nối. Ghi log ra stdout để journald thu thập. Bạn cũng có thể thêm tham số Gunicorn tùy chọn. Ví dụ, bạn chỉ định 3 worker:
/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, thêm phần [Install]
để cho systemd biết liên kết dịch vụ này với đơn vị nào khi kích hoạt khởi động cùng hệ thống. Bạn muốn dịch vụ này khởi chạy khi hệ thống multi-user bình thường:
/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
Hoàn tất tệp dịch vụ. Lưu và đóng.
Bây giờ, bạn có thể khởi động và kích hoạt socket Gunicorn. Lệnh này tạo file socket tại /run/gunicorn.sock
ngay và khi khởi động. Khi có kết nối đến socket, systemd sẽ tự động chạy gunicorn.service
để xử lý:
sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket
Bạn có thể xác nhận hoạt động bằng cách kiểm tra file socket.
Bước 8 – Kiểm tra tệp Socket của Gunicorn
Kiểm tra trạng thái quá trình để xem nó có khởi động được không:
sudo systemctl status gunicorn.socket
Bạn sẽ thấy kết quả tương tự:
Output ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled) Active: active (listening) since Mon 2022-04-18 17:53:25 UTC; 5s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) CGroup: /system.slice/gunicorn.socket Apr 18 17:53:25 django systemd[1]: Listening on gunicorn socket.
Tiếp theo, kiểm tra sự tồn tại của gunicorn.sock
trong thư mục /run
:
file /run/gunicorn.sock
Xem lại tệp /etc/systemd/system/gunicorn.socket
để khắc phục nếu cần.
Bước 9 – Kiểm tra kích hoạt socket
Hiện tại, nếu bạn chỉ khởi động gunicorn.socket
mà chưa có kết nối nào đến, gunicorn.service
sẽ chưa chạy. Kiểm tra bằng lệnh:
sudo systemctl status gunicorn
Bạn sẽ thấy mã HTML trả về từ ứng dụng. Điều này cho thấy Gunicorn đã khởi chạy và phục vụ ứng dụng Django. Kiểm tra trạng thái Gunicorn:
sudo systemctl status gunicorn
Output ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2022-04-18 17:54:49 UTC; 5s ago TriggeredBy: ● gunicorn.socket Main PID: 102674 (gunicorn) Tasks: 4 (limit: 4665) Memory: 94.2M CPU: 885ms CGroup: /system.slice/gunicorn.service ├─102674 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─102675 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─102676 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application └─102677 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application Apr 18 17:54:49 django systemd[1]: Started gunicorn daemon. Apr 18 17:54:49 django gunicorn[102674]: [2022-04-18 17:54:49 +0000] [102674] [INFO] Starting gunicorn 20.1.0 Apr 18 17:54:49 django gunicorn[102674]: [2022-04-18 17:54:49 +0000] [102674] [INFO] Listening at: unix:/run/gunicorn.sock (102674) Apr 18 17:54:49 django gunicorn[102674]: [2022-04-18 17:54:49 +0000] [102674] [INFO] Using worker: sync Apr 18 17:54:49 django gunicorn[102675]: [2022-04-18 17:54:49 +0000] [102675] [INFO] Booting worker with pid: 102675 Apr 18 17:54:49 django gunicorn[102676]: [2022-04-18 17:54:49 +0000] [102676] [INFO] Booting worker with pid: 102676 Apr 18 17:54:50 django gunicorn[102677]: [2022-04-18 17:54:50 +0000] [102677] [INFO] Booting worker with pid: 102677 Apr 18 17:54:50 django gunicorn[102675]: - - [18/Apr/2022:17:54:50 +0000] "GET / HTTP/1.1" 200 10697 "-" "curl/7.81.0"
Nếu curl
hoặc systemctl status
cho thấy lỗi, hãy xem log:
sudo journalctl -u gunicorn
Kiểm tra lại tệp /etc/systemd/system/gunicorn.service
. Nếu bạn chỉnh sửa tệp này, hãy reload daemon và khởi động lại Gunicorn:
sudo systemctl daemon-reload sudo systemctl restart gunicorn
Đảm bảo bạn xử lý xong lỗi trước khi tiếp tục.
Bước 10 – Cấu hình Nginx để chuyển tiếp yêu cầu đến Gunicorn
Khi đã thiết lập xong Gunicorn, bạn cần cấu hình Nginx để chuyển tiếp (proxy) lưu lượng đến Gunicorn.
Tạo và mở một server block mới trong thư mục sites-available
của Nginx:
sudo nano /etc/nginx/sites-available/myproject
Bên trong, mở một khối server {}
. Đầu tiên, bạn chỉ định server này lắng nghe cổng 80 thông thường, và phản hồi với tên miền hoặc IP của máy chủ:
/etc/nginx/sites-available/myproject server { listen 80; server_name server_domain_or_IP; }
Kế tiếp, bạn bảo Nginx bỏ qua lỗi liên quan đến favicon, đồng thời chỉ cho nó biết nơi chứa các tệp tĩnh trong ~/myprojectdir/static
. Tất cả các tệp này đều có tiền tố URI “/static”, nên bạn có thể tạo một khối location
để khớp các yêu cầu này:
/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, tạo một khối location / {}
để khớp mọi yêu cầu khác. Bên trong, bạn thêm proxy_params
mặc định và chuyển tiếp lưu lượng đế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 và đóng tệp khi xong. Kích hoạt cấu hình bằng cách liên kết (symlink) đến sites-enabled
:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Kiểm tra cấu hình Nginx:
sudo nginx -t
Nếu không có lỗi, hãy khởi động lại Nginx:
sudo systemctl restart nginx
Cuối cùng, bạn cần mở tường lửa để cho phép truy cập cổng 80. Vì bạn không còn cần cổng 8000 (máy chủ phát triển) nữa, hãy xóa quy tắc cũ:
sudo ufw delete allow 8000 sudo ufw allow 'Nginx Full'
Giờ bạn có thể truy cập domain hoặc IP của máy chủ để xem ứng dụng.
sudo ufw delete allow 8000 sudo ufw allow 'Nginx Full'
Nếu bạn có tên miền, cách dễ nhất để lấy chứng chỉ SSL bảo mật lưu lượng là dùng Let’s Encrypt. Hãy theo dõi hướng dẫn dành cho Ubuntu 22.04 / Ubuntu 20.04 / Ubuntu 18.04 để thiết lập Let’s Encrypt với Nginx trên Ubuntu 22.04. Thực hiện theo thủ tục, sử dụng server block Nginx bạn vừa tạo trong hướng dẫn này.
Bước 11 – Khắc phục sự cố Nginx và Gunicorn
Nếu bước cuối không hiển thị được ứng dụng, bạn cần xử lý sự cố cài đặt.
Nginx 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ì proxy đến ứng dụng, thường là do bạn cần chỉnh server_name
trong /etc/nginx/sites-available/myproject
trỏ đến IP hoặc domain của máy chủ.
Nginx dùng server_name
để quyết định block nào sẽ phản hồi yêu cầu. Nếu bạn thấy trang mặc định, nghĩa là Nginx không khớp được request với block cụ thể, nên nó quay về block mặc định trong /etc/nginx/sites-available/default
.
server_name
trong block dự án phải cụ thể hơn block mặc định để được chọn.
Nginx đang hiển thị lỗi 502 Bad Gateway thay vì ứng dụng Django.
Mã 502 cho biết Nginx không thể proxy yêu cầu thành công. Nhiều lỗi cấu hình khác nhau có thể gây ra 502, nên bạn cần thông tin chi tiết hơn.
Nơi tốt nhất để kiểm tra là error logs của Nginx:
sudo tail -F /var/log/nginx/error.log
Tiếp theo, làm mới trang để tạo lỗi mới. Bạn sẽ thấy log lỗi mới. Đọc thông báo sẽ giúp thu hẹp nguyên nhân.
Bạn có thể gặp thông báo:
connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)
Điều này có nghĩa Nginx không tìm thấy gunicorn.sock
tại vị trí được chỉ định. So sánh đường dẫn proxy_pass
trong /etc/nginx/sites-available/myproject
với vị trí thực của gunicorn.sock
được tạo bởi gunicorn.socket
.
Nếu bạn không tìm thấy gunicorn.sock
trong /run
, có thể systemd socket
không tạo được file này. Hãy quay lại phần kiểm tra file socket Gunicorn để xử lý.
Hoặc bạn gặp thông báo:
connect() to unix:/run/gunicorn.sock failed (13: Permission denied)
Nghĩa là Nginx không kết nối được đến socket Gunicorn do vấn đề quyền truy cập. Thường xảy ra nếu bạn thao tác bằng tài khoản root thay vì sudo user. Mặc dù systemd tạo được socket, Nginx không thể truy cập nó.
Điều này có thể do quyền hạn bị giới hạn ở bất kỳ thư mục nào từ /
đến gunicorn.sock
. Bạn có thể kiểm tra quyền và chủ sở hữu của socket và các thư mục cha bằng lệnh:
namei -l /run/gunicorn.sock
namei -l /run/gunicorn.sock
Dựa trên cột quyền (permissions), chủ sở hữu (owner), nhóm (group), bạn sẽ biết quyền truy cập thế nào.
Trong ví dụ trên, socket và các thư mục dẫn đến nó đều có quyền “read và execute” cho mọi người (thư mục có r-x
). Nhờ vậy, Nginx có thể truy cập socket.
Nếu bất kỳ thư mục nào thiếu quyền r-x
cho mọi người, Nginx không thể truy cập socket trừ khi bạn cấp quyền này cho mọi người hoặc đảm bảo nhóm sở hữu là một nhóm mà Nginx tham gia.
Django hiển thị: “không thể kết nối đến máy chủ: Kết nối bị từ chối”
Bạn có thể thấy thông báo này khi truy cập một phần nào đó của ứng dụng:
Nếu Postgres không chạy, bạn có thể khởi động và bật nó tự động chạy khi khởi động:
sudo systemctl start postgresql sudo systemctl enable postgresql
Nếu vẫn lỗi, hãy kiểm tra lại cài đặt database trong ~/myprojectdir/myproject/settings.py
.
Khắc phục sự cố thêm
Để xử lý thêm, bạn có thể xem log để tìm manh mối. Kiểm tra lần lượt:
- Log tiến trình Nginx:
sudo journalctl -u nginx
- Log truy cập Nginx:
sudo less /var/log/nginx/access.log
- Log lỗi Nginx:
sudo less /var/log/nginx/error.log
- Log ứng dụng Gunicorn:
sudo journalctl -u gunicorn
- Log socket Gunicorn:
sudo journalctl -u gunicorn.socket
Khi bạn cập nhật cấu hình hoặc ứng dụng, có thể cần khởi động lại tiến trình.
Kết luận
Với hướng dẫn này, bạn đã hoàn tất việc thiết lập một dự án Django trong môi trường ảo, đảm bảo tính độc lập và quản lý dễ dàng các dependencies. Bạn cũng đã cấu hình Gunicorn để xử lý các yêu cầu HTTP và chuyển tiếp chúng đến ứng dụng Django, đồng thời triển khai Nginx làm reverse proxy để tối ưu hóa hiệu suất và bảo mật khi phục vụ nội dung đến người dùng.
Django mang lại sự linh hoạt và mạnh mẽ trong việc phát triển ứng dụng web, giúp bạn tận dụng các thành phần có sẵn để tập trung vào logic nghiệp vụ cốt lõi. Bằng cách áp dụng các công nghệ và kỹ thuật triển khai được đề cập trong bài viết này, bạn có thể dễ dàng quản lý, mở rộng và triển khai các ứng dụng Django một cách hiệu quả trên máy chủ sản xuất.