如何在 Ubuntu 20.04 上使用 Postgres、Nginx 和 Gunicorn 设置 Django

介绍

Django 是一个强大的 Web 框架,可以帮助您启动 Python 应用程序或网站。Django 包含一个简化的开发服务器,用于在本地测试您的代码,但是对于任何与生产相关的事情,都需要一个更安全、更强大的 Web 服务器。

在本指南中,我们将演示如何在 Ubuntu 20.04 上安装和配置一些组件以支持和服务 Django 应用程序。我们将设置一个 PostgreSQL 数据库,而不是使用默认的 SQLite 数据库。我们将配置 Gunicorn 应用程序服务器以与我们的应用程序交互。然后,我们将设置 Nginx 以反向代理到 Gunicorn,让我们可以访问其安全和性能功能来为我们的应用程序提供服务。

先决条件和目标

为了完成本指南,您应该有一个全新的 Ubuntu 20.04 服务器实例,带有基本防火墙和sudo配置权限的非 root 用户您可以通过阅读我们的初始服务器设置指南来了解如何进行设置

我们将在虚拟环境中安装 Django。将 Django 安装到特定于您的项目的环境中将允许单独处理您的项目及其要求。

一旦我们的数据库和应用程序启动并运行,我们将安装和配置 Gunicorn 应用程序服务器。这将作为我们应用程序的接口,将客户端请求从 HTTP 转换为我们的应用程序可以处理的 Python 调用。然后,我们将在 Gunicorn 面前设置 Nginx,以利用其高性能连接处理机制和易于实现的安全功能。

让我们开始吧。

从 Ubuntu 存储库安装软件包

为了开始这个过程,我们将从 Ubuntu 存储库下载并安装我们需要的所有项目。稍后我们将使用 Python 包管理器pip安装其他组件。

我们需要更新本地apt包索引,然后下载并安装包。我们安装的包取决于您的项目将使用的 Python 版本。

如果您在Python 3中使用 Django ,请输入:

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

Django 1.11 是 Django 的最后一个版本,将支持 Python 2。如果您正在开始新项目,强烈建议您选择 Python 3。如果您仍然需要使用Python 2,请键入:

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

这将安装pip、稍后构建 Gunicorn 所需的 Python 开发文件、Postgres 数据库系统和与其交互所需的库,以及 Nginx Web 服务器。

创建 PostgreSQL 数据库和用户

我们将直接进入并为我们的 Django 应用程序创建一个数据库和数据库用户。

默认情况下,Postgres 对本地连接使用称为“对等身份验证”的身份验证方案。基本上,这意味着如果用户的操作系统用户名与有效的 Postgres 用户名匹配,则该用户无需进一步身份验证即可登录。

在 Postgres 安装期间,postgres创建了一个名为的操作系统用户以对应于postgresPostgreSQL 管理用户。我们需要使用这个用户来执行管理任务。我们可以使用 sudo 并通过-u选项传入用户名

通过键入以下内容登录交互式 Postgres 会话:

  • sudo -u postgres psql

您将收到一个 PostgreSQL 提示,我们可以在其中设置我们的要求。

首先,为您的项目创建一个数据库:

  • CREATE DATABASE myproject;

注意:每个 Postgres 语句都必须以分号结尾,因此如果遇到问题,请确保您的命令以分号结尾。

接下来,为我们的项目创建一个数据库用户。确保选择安全密码:

  • CREATE USER myprojectuser WITH PASSWORD 'password';

之后,我们将为我们刚刚创建的用户修改一些连接参数。这将加速数据库操作,以便每次建立连接时不必查询和设置正确的值。

我们将默认编码设置为UTF-8Django 所期望的。我们还将默认事务隔离方案设置为“已提交读”,这会阻止从未提交的事务中读取。最后,我们正在设置时区。默认情况下,我们的 Django 项目将设置为使用UTC. 这些都是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';

现在,我们可以授予新用户访问权限来管理我们的新数据库:

  • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

完成后,键入以下命令退出 PostgreSQL 提示符:

  • \q

Postgres 现在已设置,以便 Django 可以连接到并管理其数据库信息。

为您的项目创建 Python 虚拟环境

现在我们有了我们的数据库,我们可以开始准备其余的项目需求。我们将在虚拟环境中安装我们的 Python 需求,以便于管理。

为此,我们首先需要访问该virtualenv命令。我们可以用pip.

如果您使用的是Python 3pip请键入以下内容升级并安装包:

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

如果您使用的是Python 2pip请键入以下内容升级并安装包:

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

随着virtualenv安装,我们可以开始形成我们的项目。创建并移动到一个目录,我们可以在其中保存我们的项目文件:

  • mkdir ~/myprojectdir
  • cd ~/myprojectdir

在项目目录中,通过键入以下内容创建 Python 虚拟环境:

  • virtualenv myprojectenv

这将创建一个myprojectenv在您的目录中调用myprojectdir目录。在里面,它将安装本地版本的 Python 和本地版本的pip. 我们可以使用它为我们的项目安装和配置隔离的 Python 环境。

在安装项目的 Python 要求之前,我们需要激活虚拟环境。您可以通过键入:

  • source myprojectenv/bin/activate

您的提示应更改以指示您现在正在 Python 虚拟环境中操作。它会是这个样子:(myprojectenv)user@host:~/myprojectdir$

在您的虚拟环境处于活动状态时,psycopg2使用以下本地实例安装 Django、Gunicorn 和PostgreSQL 适配器pip

注意:当激活虚拟环境时(当您的提示(myprojectenv)前面有提示时),即使您使用的是 Python 3,也请使用pip代替pip3。该工具的虚拟环境副本始终命名为pip,无论 Python 版本如何。

  • pip install django gunicorn psycopg2-binary

您现在应该拥有启动 Django 项目所需的所有软件。

创建和配置新的 Django 项目

安装我们的 Python 组件后,我们可以创建实际的 Django 项目文件。

创建 Django 项目

由于我们已经有一个项目目录,我们将告诉 Django 在此处安装文件。它会创建一个带有实际代码的二级目录,这是正常的,并在该目录中放置一个管理脚本。关键是我们明确定义了目录,而不是让 Django 做出相对于我们当前目录的决定:

  • django-admin.py startproject myproject ~/myprojectdir

此时,您的项目目录(在我们的例子中)应该有以下内容:~/myprojectdir

  • ~/myprojectdir/manage.py: 一个 Django 项目管理脚本。
  • ~/myprojectdir/myproject/: Django 项目包。这应该包括__init__.pysettings.pyurls.pyasgi.py,和wsgi.py文件。
  • ~/myprojectdir/myprojectenv/:我们之前创建的虚拟环境目录。

调整项目设置

我们应该对新创建的项目文件做的第一件事是调整设置。在文本编辑器中打开设置文件:

  • nano ~/myprojectdir/myproject/settings.py

首先找到ALLOWED_HOSTS指令。这定义了可用于连接到 Django 实例的服务器地址或域名列表。任何具有不在此列表中Host标头的传入请求都将引发异常。Django 要求您设置此项以防止某类安全漏洞。

在方括号中,列出与您的 Django 服务器关联的 IP 地址或域名。每一项都应列在引号中,条目用逗号分隔。如果您希望请求整个域和任何子域,请在条目的开头添加一个句点。在下面的代码段中,有一些注释掉的示例用于演示:

注意:请务必localhost作为选项之一包含在内,因为我们将通过本地 Nginx 实例代理连接。

~/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']

接下来,找到配置数据库访问的部分。它将以DATABASES. 文件中的配置用于 SQLite 数据库。我们已经为我们的项目创建了一个 PostgreSQL 数据库,所以我们需要调整设置。

使用 PostgreSQL 数据库信息更改设置。我们告诉 Django 使用psycopg2我们安装适配器pip我们需要给出数据库名称、数据库用户名、数据库用户密码,然后指定数据库位于本地计算机上。您可以将PORT设置保留为空字符串:

~/myprojectdir/myproject/settings.py
. . .

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

. . .

接下来,向下移动到文件底部并添加一个设置,指示应该放置静态文件的位置。这是必要的,以便 Nginx 可以处理对这些项目的请求。以下行告诉 Django 将它们放置static在基础项目目录中调用的目录中:

~/myprojectdir/myproject/settings.py
. . .

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

完成后保存并关闭文件。

完成初始项目设置

现在,我们可以使用管理脚本将初始数据库架构迁移到我们的 PostgreSQL 数据库:

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

通过键入以下内容为项目创建管理用户:

  • ~/myprojectdir/manage.py createsuperuser

您必须选择用户名,提供电子邮件地址,然后选择并确认密码。

我们可以通过键入以下内容将所有静态内容收集到我们配置的目录位置:

  • ~/myprojectdir/manage.py collectstatic

您必须确认操作。然后,静态文件将放置在static项目目录中调用的目录中。

如果您遵循初始服务器设置指南,您应该有一个 UFW 防火墙来保护您的服务器。为了测试开发服务器,我们必须允许访问我们将使用的端口。

通过键入以下内容为端口 8000 创建例外:

  • sudo ufw allow 8000

最后,您可以通过使用以下命令启动 Django 开发服务器来测试我们的项目:

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

在您的网络浏览器中,访问您服务器的域名或 IP 地址,后跟:8000

http://server_domain_or_IP:8000

您应该会收到默认的 Django 索引页面:

Django 索引页

如果您附加/admin到地址栏中 URL 的末尾,系统将提示您输入使用以下createsuperuser命令创建的管理用户名和密码

Django 管理员登录

验证后,您可以访问默认的 Django 管理界面:

Django 管理界面

完成探索后,在终端窗口中按CTRL-C关闭开发服务器。

测试 Gunicorn 服务项目的能力

在离开我们的虚拟环境之前,我们要做的最后一件事是测试 Gunicorn 以确保它可以为应用程序提供服务。我们可以通过进入我们的项目目录并使用gunicorn加载项目的 WSGI 模块来做到这一点

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

这将在运行 Django 开发服务器的同一界面上启动 Gunicorn。您可以返回并再次测试该应用程序。

注意:管理界面不会应用任何样式,因为 Gunicorn 不知道如何找到对此负责的静态 CSS 内容。

我们通过wsgi.py使用 Python 的模块语法指定 Django文件的相对目录路径向 Gunicorn 传递一个模块,该文件是我们应用程序的入口点。在这个文件中,application定义了一个被调用的函数,用于与应用程序进行通信。要了解有关 WSGI 规范的更多信息,请单击此处

完成测试后,在终端窗口中按CTRL-C以停止 Gunicorn。

我们现在已经完成了 Django 应用程序的配置。我们可以通过键入以下内容退出我们的虚拟环境:

  • deactivate

提示中的虚拟环境指示器将被删除。

为 Gunicorn 创建 systemd 套接字和服务文件

我们已经测试过 Gunicorn 可以与我们的 Django 应用程序交互,但是我们应该实现一种更健壮的方式来启动和停止应用程序服务器。为此,我们将制作 systemd 服务和套接字文件。

Gunicorn 套接字将在启动时创建并监听连接。当连接发生时,systemd 会自动启动 Gunicorn 进程来处理连接。

首先为 Gunicorn 创建并打开一个具有sudo特权的 systemd 套接字文件

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

在里面,我们将创建一个[Unit]描述套接字的[Socket]部分,一个定义套接字位置的[Install]部分,以及一个确保在正确的时间创建套接字部分:

/etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

完成后保存并关闭文件。

接下来,sudo在文本编辑器中使用权限为 Gunicorn 创建并打开 systemd 服务文件服务文件名应与套接字文件名匹配,但扩展名除外:

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

[Unit]用于指定元数据和依赖项部分开始我们将在此处描述我们的服务,并告诉 init 系统仅在达到网络目标后才启动它。因为我们的服务依赖于套接字文件中的套接字,所以我们需要包含一个Requires指令来指示这种关系:

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

接下来,我们将打开该[Service]部分。我们将指定要在其下运行的用户和组。我们将授予我们的常规用户帐户所有权,因为它拥有所有相关文件。我们将给组赋予组所有权,www-data以便 Nginx 可以轻松地与 Gunicorn 通信。

然后我们将绘制工作目录并指定用于启动服务的命令。在这种情况下,我们必须指定 Gunicorn 可执行文件的完整路径,该文件安装在我们的虚拟环境中。我们将进程绑定到我们在/run目录中创建的 Unix 套接字,以便进程可以与 Nginx 通信。我们将所有数据记录到标准输出,以便该journald过程可以收集 Gunicorn 日志。我们还可以在此处指定任何可选的 Gunicorn 调整。例如,我们在这种情况下指定了 3 个工作进程:

/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]部分。如果我们启用它在启动时启动,这将告诉 systemd 将该服务链接到什么。我们希望此服务在常规多用户系统启动并运行时启动:

/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

至此,我们的 systemd 服务文件就完成了。现在保存并关闭它。

我们现在可以启动并启用 Gunicorn 套接字。这将在/run/gunicorn.sock现在和启动时创建套接字文件当与该套接字建立连接时,systemd 将自动启动gunicorn.service来处理它:

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

我们可以通过检查socket文件来确认操作成功。

检查 Gunicorn 套接字文件

检查进程的状态以确定它是否能够启动:

  • sudo systemctl status gunicorn.socket

您应该会收到如下输出:

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

接下来,检查目录中是否存在该gunicorn.sock文件/run

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

如果该systemctl status命令表明发生了错误,或者如果您gunicorn.sock在目录中找不到该文件,则表明无法正确创建 Gunicorn 套接字。通过键入以下内容检查 Gunicorn 套接字的日志:

  • sudo journalctl -u gunicorn.socket

/etc/systemd/system/gunicorn.socket在继续之前,请再次查看您的文件以解决任何问题。

测试套接字激活

目前,如果您只启动了该gunicorn.socket单元,则单元gunicorn.service还不会处于活动状态,因为套接字尚未收到任何连接。您可以通过键入以下内容进行检查:

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

要测试套接字激活机制,我们可以curl通过键入以下内容发送到套接字的连接

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

您应该在终端中收到来自应用程序的 HTML 输出。这表明 Gunicorn 已启动并且能够为您的 Django 应用程序提供服务。您可以通过键入以下内容来验证 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 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

如果来自curl或的输出systemctl status表明发生了问题,请检查日志以获取其他详细信息:

  • sudo journalctl -u gunicorn

检查您的/etc/systemd/system/gunicorn.service文件是否有问题。如果您对/etc/systemd/system/gunicorn.service文件进行了更改,请重新加载守护程序以重新读取服务定义并通过键入以下内容重新启动 Gunicorn 进程:

  • sudo systemctl daemon-reload
  • sudo systemctl restart gunicorn

在继续之前,请确保对上述问题进行故障排除。

配置 Nginx 到 Gunicorn 的代理传递

现在 Gunicorn 设置完毕,我们需要配置 Nginx 以将流量传递给进程。

首先在 Nginx 的sites-available目录中创建并打开一个新的服务器块

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

在里面,打开一个新的服务器块。我们将首先指定此块应侦听正常端口 80 并应响应我们服务器的域名或 IP 地址:

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

接下来,我们将告诉 Nginx 忽略查找图标的任何问题。我们还将告诉它在哪里可以找到我们在目录中收集的静态资产所有这些文件都有一个标准的 URI 前缀“/static”,所以我们可以创建一个位置块来匹配这些请求:~/myprojectdir/static

/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 / {}块来匹配所有其他请求。在此位置内,我们将包含proxy_paramsNginx 安装中包含的标准文件,然后将流量直接传递到 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;
    }
}

完成后保存并关闭文件。现在,我们可以通过将文件链接到sites-enabled目录来启用该文件

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

通过键入以下内容来测试您的 Nginx 配置是否存在语法错误:

  • sudo nginx -t

如果没有报告错误,请继续并通过键入以下内容重新启动 Nginx:

  • sudo systemctl restart nginx

最后,我们需要打开我们的防火墙以允许 80 端口上的正常流量。由于我们不再需要访问开发服务器,我们也可以删除打开 8000 端口的规则:

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

您现在应该可以转到您服务器的域或 IP 地址来查看您的应用程序。

注意:配置 Nginx 后,下一步应该是使用 SSL/TLS 保护到服务器的流量。这很重要,因为没有它,包括密码在内的所有信息都以纯文本形式通过网络发送。

如果您有域名,获取 SSL 证书以保护您的流量的最简单方法是使用 Let’s Encrypt。按照本指南在 Ubuntu 20.04 上使用 Nginx 设置 Let’s Encrypt。按照使用我们在本指南中创建的 Nginx 服务器块的过程进行操作。

Nginx 和 Gunicorn 故障排除

如果最后一步没有显示您的应用程序,您将需要对安装进行故障排除。

Nginx 显示默认页面而不是 Django 应用程序

如果 Nginx 显示默认页面而不是代理到您的应用程序,通常意味着您需要调整文件server_name内的指向您服务器的 IP 地址或域名。/etc/nginx/sites-available/myproject

Nginx 使用server_name来确定使用哪个服务器块来响应请求。如果您收到默认的 Nginx 页面,则表明 Nginx 无法明确地将请求与服务器块匹配,因此它会退回到/etc/nginx/sites-available/default.

server_name您的项目中的服务器块必须更具体的一个比默认的服务器块被选中。

Nginx 显示 502 Bad Gateway 错误而不是 Django 应用程序

502 错误表示 Nginx 无法成功代理请求。大量配置问题以 502 错误表示,因此需要更多信息才能正确排除故障。

查找更多信息的主要位置是 Nginx 的错误日志。通常,这会告诉您在代理事件期间哪些条件导致了问题。通过键入以下内容来跟踪 Nginx 错误日志:

  • sudo tail -F /var/log/nginx/error.log

现在,在浏览器中发出另一个请求以生成新错误(尝试刷新页面)。您应该会收到一条写入日志的新错误消息。如果您查看该消息,它应该可以帮助您缩小问题的范围。

您可能会收到以下消息:

connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

这表明 Nginx 无法gunicorn.sock在给定位置找到该文件。您应该将文件中proxy_pass定义/etc/nginx/sites-available/myproject的位置gunicorn.sockgunicorn.socketsystemd 单元生成文件的实际位置进行比较

如果gunicorn.sock/run目录中找不到文件,通常意味着 systemd 套接字文件无法创建它。返回检查 Gunicorn 套接字文件的部分,逐步完成 Gunicorn 的故障排除步骤。

connect() 到 unix:/run/gunicorn.sock 失败(13:权限被拒绝)

这表示由于权限问题,Nginx 无法连接到 Gunicorn 套接字。当使用 root 用户而不是sudo用户执行该过程时,可能会发生这种情况虽然 systemd 能够创建 Gunicorn 套接字文件,但 Nginx 无法访问它。

如果根目录 ( /)gunicorn.sock文件之间的任何一点权限有限,就会发生这种情况我们可以通过将套接字文件的绝对路径传递给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

输出显示每个目录组件的权限。通过查看权限(第一列)、所有者(第二列)和组所有者(第三列),我们可以确定允许访问套接字文件的类型。

在上面的示例中,套接字文件和通向套接字文件的每个目录都具有全局读取和执行权限(目录的权限列以 结尾,r-x而不是---)。Nginx 进程应该能够成功访问套接字。

如果通向套接字的任何目录没有全局读取和执行权限,Nginx 将无法访问套接字,除非允许全局读取和执行权限或确保将组所有权授予 Nginx 所属的组的。

Django 显示:“无法连接到服务器:连接被拒绝”

当您尝试在 Web 浏览器中访问应用程序的某些部分时,您可能会从 Django 收到一条消息:

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?

这表示 Django 无法连接到 Postgres 数据库。通过键入以下内容确保 Postgres 实例正在运行:

  • sudo systemctl status postgresql

如果不是,您可以通过键入以下内容来启动它并使其在引导时自动启动(如果尚未配置为这样做):

  • sudo systemctl start postgresql
  • sudo systemctl enable postgresql

如果仍有问题,请确保~/myprojectdir/myproject/settings.py文件中定义的数据库设置正确。

进一步故障排除

对于其他故障排除,日志可以帮助缩小根本原因。依次检查每一个并查找指示问题区域的消息。

以下日志可能会有所帮助:

  • 通过键入以下内容检查 Nginx 进程日志: sudo journalctl -u nginx
  • 通过键入以下内容检查 Nginx 访问日志: sudo less /var/log/nginx/access.log
  • 通过键入以下内容检查 Nginx 错误日志: sudo less /var/log/nginx/error.log
  • 通过键入以下内容检查 Gunicorn 应用程序日志: sudo journalctl -u gunicorn
  • 通过键入以下内容检查 Gunicorn 套接字日志: sudo journalctl -u gunicorn.socket

当您更新配置或应用程序时,您可能需要重新启动进程以适应您的更改。

如果您更新了 Django 应用程序,您可以通过键入以下内容重新启动 Gunicorn 进程以获取更改:

  • sudo systemctl restart gunicorn

如果您更改 Gunicorn 套接字或服务文件,请重新加载守护程序并通过键入以下内容重新启动进程:

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

如果您更改了 Nginx 服务器块配置,请通过键入以下内容来测试配置和 Nginx:

  • sudo nginx -t && sudo systemctl restart nginx

这些命令有助于在您调整配置时获取更改。

结论

在本指南中,我们在自己的虚拟环境中设置了一个 Django 项目。我们已经配置 Gunicorn 来翻译客户端请求,以便 Django 可以处理它们。之后,我们设置 Nginx 作为反向代理来处理客户端连接并根据客户端请求为正确的项目提供服务。

Django 通过提供许多通用部分使创建项目和应用程序变得简单,让您可以专注于独特的元素。通过利用本文中描述的通用工具链,您可以轻松地为从单个服务器创建的应用程序提供服务。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁