如何在Debian 10上使用Postgres,Nginx和Gunicorn设置Django

2021-06-16 10:21:25 浏览数 (1)

介绍

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

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

先决条件

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

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

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

让我们开始吧。

第1步 - 从Debian存储库安装软件包

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

我们首先需要更新本地apt包索引,然后下载并安装包。

在本指南中,我们将使用Django和Python 3.要安装必要的库,请登录到您的服务器并键入:

代码语言:javascript复制
sudo apt update
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

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

第2步 - 创建PostgreSQL数据库和用户

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

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

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

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

代码语言:javascript复制
sudo -u postgres psql

您将获得PostgreSQL提示符,我们可以在其中设置我们的要求。

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

代码语言:javascript复制
CREATE DATABASE myproject;

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

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

代码语言:javascript复制
CREATE USER myprojectuser WITH PASSWORD 'password';

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

我们将默认编码设置为UTF-8 ,这是Django所期望的。 我们还将默认事务隔离方案设置为“read committed”,它阻止从未提交的事务中读取。 最后,我们正在设定时区。 默认情况下,我们的Django项目将设置为使用UTC 。 这些都是Django项目本身的建议:

代码语言:javascript复制
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';

现在,我们可以为新用户提供管理新数据库的权限:

代码语言:javascript复制
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

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

代码语言:javascript复制
q

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

第3步 - 为您的项目创建Python虚拟环境

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

为此,我们首先需要访问virtualenv命令。 我们可以用pip安装它。

通过输入以下命令升级pip并安装包:

代码语言:javascript复制
sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv

安装virtualenv ,我们就可以开始virtualenv我们的项目了。 创建并移动到我们可以保存项目文件的目录:

代码语言:javascript复制
mkdir ~/myprojectdir
cd ~/myprojectdir

在项目目录中,键入以下命令创建Python虚拟环境:

代码语言:javascript复制
virtualenv myprojectenv

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

在我们安装项目的Python需求之前,我们需要激活虚拟环境。 您可以输入以下命令:

代码语言:javascript复制
source myprojectenv/bin/activate

您的提示应更改为表明您现在在Python虚拟环境中运行。 它看起来像这样: ( myprojectenv ) user @ host :~/ myprojectdir $

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

注意:当虚拟环境被激活时(当你的提示在其前面有(myprojectenv)时),使用pip而不是pip3 ,即使你使用的是Python 3.虚拟环境的工具副本总是命名为pip ,不管Python是什么版。

代码语言:javascript复制
pip install django gunicorn psycopg2-binary

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

第4步 - 创建和配置新的Django项目

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

创建Django项目

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

代码语言:javascript复制
django-admin.py startproject myproject ~/myprojectdir

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

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

调整项目设置

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

代码语言:javascript复制
nano ~/myprojectdir/myproject/settings.py

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

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

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

〜/ myprojectdir / myproject的/ settings.py

代码语言:javascript复制
. . .
# 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使用我们用pip安装的psycopg2适配器。 我们需要提供数据库名称,数据库用户名,数据库用户的密码,然后指定数据库位于本地计算机上。 您可以将PORT设置保留为空字符串:

〜/ myprojectdir / myproject的/ settings.py

代码语言:javascript复制
. . .

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

. . .

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

〜/ myprojectdir / myproject的/ settings.py

代码语言:javascript复制
. . .

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

完成后保存并关闭文件。

完成初始项目设置

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

代码语言:javascript复制
~/myprojectdir/manage.py makemigrations
~/myprojectdir/manage.py migrate

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

代码语言:javascript复制
~/myprojectdir/manage.py createsuperuser

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

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

代码语言:javascript复制
~/myprojectdir/manage.py collectstatic

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

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

键入以下命令为端口8000创建例外:

代码语言:javascript复制
sudo ufw allow 8000

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

代码语言:javascript复制
~/myprojectdir/manage.py runserver 0.0.0.0:8000

在Web浏览器中,访问服务器的域名或IP地址,然后访问:8000

代码语言:javascript复制
http://server_domain_or_IP:8000

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

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

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

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

测试Gunicorn服务项目的能力

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

代码语言:javascript复制
cd ~/myprojectdir
gunicorn --bind 0.0.0.0:8000 myproject.wsgi

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

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

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

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

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

代码语言:javascript复制
deactivate

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

第5步 - 为Gunicorn创建systemd套接字和服务文件

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

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

首先使用sudo权限为Gunicorn创建和打开systemd套接字文件:

代码语言:javascript复制
sudo nano /etc/systemd/system/gunicorn.socket

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

/etc/systemd/system/gunicorn.socket

代码语言:javascript复制
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

完成后保存并关闭文件。

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

代码语言:javascript复制
sudo nano /etc/systemd/system/gunicorn.service

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

/etc/systemd/system/gunicorn.service

代码语言:javascript复制
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

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

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

/etc/systemd/system/gunicorn.service

代码语言:javascript复制
[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

代码语言:javascript复制
[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来处理它:

代码语言:javascript复制
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

我们可以通过检查套接字文件来确认操作是否成功。

第6步 - 检查Gunicorn套接字文件

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

代码语言:javascript复制
sudo systemctl status gunicorn.socket

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

代码语言:javascript复制
file /run/gunicorn.sock
代码语言:javascript复制
Output/run/gunicorn.sock: socket

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

代码语言:javascript复制
sudo journalctl -u gunicorn.socket

再看看你的/etc/systemd/system/gunicorn.socket文件来解决任何问题,然后再继续。

第7步 - 测试套接字激活

目前,如果您只启动了gunicorn.socket单元,则gunicorn.service将不会处于活动状态,因为套接字尚未接收任何连接。 您可以输入以下命令来检查:

代码语言:javascript复制
sudo systemctl status gunicorn
代码语言:javascript复制
Output● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

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

代码语言:javascript复制
curl --unix-socket /run/gunicorn.sock localhost

您应该在终端中看到应用程序的HTML输出。 这表明Gunicorn已经启动并能够为您的Django应用程序提供服务。 您可以通过键入以下内容来验证Gunicorn服务是否正在运行:

代码语言:javascript复制
sudo systemctl status gunicorn
代码语言:javascript复制
Output● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
   Active: active (running) since Mon 2018-07-09 20:00:40 UTC; 4s ago
 Main PID: 1157 (gunicorn)
    Tasks: 4 (limit: 1153)
   CGroup: /system.slice/gunicorn.service
           ├─1157 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application
           ├─1178 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application
           ├─1180 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application
           └─1181 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application

Jul 09 20:00:40 django1 systemd[1]: Started gunicorn daemon.
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40  0000] [1157] [INFO] Starting gunicorn 19.9.0
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40  0000] [1157] [INFO] Listening at: unix:/run/gunicorn.sock (1157)
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40  0000] [1157] [INFO] Using worker: sync
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40  0000] [1178] [INFO] Booting worker with pid: 1178
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40  0000] [1180] [INFO] Booting worker with pid: 1180
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40  0000] [1181] [INFO] Booting worker with pid: 1181
Jul 09 20:00:41 django1 gunicorn[1157]:  - - [09/Jul/2018:20:00:41  0000] "GET / HTTP/1.1" 200 16348 "-" "curl/7.58.0"

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

代码语言:javascript复制
sudo journalctl -u gunicorn

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

代码语言:javascript复制
sudo systemctl daemon-reload
sudo systemctl restart gunicorn

请确保在继续之前解决上述问题。

第8步 - 配置Nginx到代理传递给Gunicorn

现在Gunicorn已经建立,我们需要配置Nginx以将流量传递给进程。

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

代码语言:javascript复制
sudo nano /etc/nginx/sites-available/myproject

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

在/ etc / nginx的/网站可用/ myproject的

代码语言:javascript复制
server {
    listen 80;
    server_name server_domain_or_IP;
}

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

在/ etc / nginx的/网站可用/ myproject的

代码语言:javascript复制
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 / {}块来匹配所有其他请求。 在这个位置的内部,我们将包含Nginx安装中包含的标准proxy_params文件,然后我们将流量直接传递给Gunicorn套接字:

在/ etc / nginx的/网站可用/ myproject的

代码语言:javascript复制
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目录来启用该文件:

代码语言:javascript复制
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

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

代码语言:javascript复制
sudo nginx -t

如果没有报告错误,请输入以下命令重新启动Nginx:

代码语言:javascript复制
sudo systemctl restart nginx

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

代码语言:javascript复制
sudo ufw delete allow 8000
sudo ufw allow 'Nginx Full'

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

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

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

如果您没有域名,您仍然可以使用自签名SSL证书保护您的站点以进行测试和学习。 再次,使用我们在本教程中创建的Nginx服务器块来执行该过程。

对Nginx和Gunicorn进行故障排除

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

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

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

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

项目服务器块中的server_name必须比要选择的默认服务器块中的server_name更具体。

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

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

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

代码语言:javascript复制
sudo tail -F /var/log/nginx/error.log

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

您可能会看到以下消息:

connect()到unix:/run/gunicorn.sock失败(2:没有这样的文件或目录)

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

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

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

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

如果根目录( gunicorn.sock文件之间的任何点上的权限有限,则会发生这种情况。 我们可以通过将socket文件的绝对路径传递给namei命令来查看套接字文件及其每个父目录的权限和所有权值:

代码语言:javascript复制
namei -l /run/gunicorn.sock
代码语言:javascript复制
Outputf: /run/gunicorn.sock
drwxr-xr-x root root /
drwxr-xr-x root root run
srw-rw-rw- root root gunicorn.sock

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

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

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

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

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

代码语言:javascript复制
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实例正在运行:

代码语言:javascript复制
sudo systemctl status postgresql

如果不是,则可以通过键入以下内容启动它并使其在启动时自动启动(如果尚未配置为启动):

代码语言:javascript复制
sudo systemctl start postgresql
sudo systemctl enable postgresql

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

进一步排除故

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

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

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

在更新配置或应用程序时,可能需要重新启动进程以根据更改进行调整。

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

代码语言:javascript复制
sudo systemctl restart gunicorn

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

代码语言:javascript复制
sudo systemctl daemon-reload
sudo systemctl restart gunicorn.socket gunicorn.service

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

代码语言:javascript复制
sudo nginx -t && sudo systemctl restart nginx

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

结论

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

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

您可以通过将静态资产(如Javascript和CSS)卸载到CDN或对象存储服务来进一步优化此设置。 要了解如何使用DigitalOcean Spaces CDN执行此操作,请参阅如何使用DigitalOcean托管数据库和空间设置可扩展Django应用程序 。 本教程还将向您展示如何使用Nginx,Let's Encrypt和Django配置SSL / TLS / HTTPS。

0 人点赞