如何在Debian 11上用Postgres、Nginx和Gunicorn设置Django

136 阅读23分钟

简介

Django是一个强大的网络框架,可以帮助你的Python应用程序或网站起步。Django包括一个开发服务器,用于在本地测试你的代码,但对于任何与生产有关的事情,都需要一个更安全、更强大的网络服务器。

在本指南中,你将在 Debian 11 上安装和配置一些组件,以支持和服务 Django 应用程序。你将设置一个PostgreSQL数据库,而不是使用默认的SQLite数据库。你将配置Gunicorn应用服务器来与你的应用程序对接。然后你将设置Nginx来反向代理Gunicorn,使你能够使用它的安全和性能特性来服务你的应用程序。

先决条件和目标

为了完成本指南,你应该有一个新的Debian 11服务器实例,有一个基本的防火墙和一个配置了sudo 权限的非root用户。

你将在一个虚拟环境中安装Django。将Django安装在一个特定于你的项目的环境中,将允许你的项目和他们的需求被分开处理。

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

让我们开始吧。

从Debian软件库中安装软件包

为了开始这个过程,你将从Debian软件库中下载并安装所有你需要的东西。稍后你将使用 Python 软件包管理器pip 来安装其他组件。

首先,您需要更新本地apt 软件包索引,然后下载并安装这些软件包。

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

这个命令将安装一个为你的Python项目创建虚拟环境的工具,以后构建Gunicorn所需的Python开发文件,Postgres数据库系统和与之交互的库,以及Nginx网络服务器。

创建PostgreSQL数据库和用户

现在你可以直接进入,为我们的Django应用程序创建一个数据库和数据库用户。

默认情况下,Postgres对本地连接使用一种叫做 "对等认证 "的认证方案。基本上,这意味着如果用户的操作系统用户名与有效的Postgres用户名相匹配,该用户就可以登录,而无需进一步的认证。

在Postgres安装过程中,创建了一个名为postgres 的操作系统用户,与postgres PostgreSQL管理用户对应。你需要使用这个用户来执行管理任务。你可以使用sudo并通过-u 选项输入用户名。

通过键入登录到一个交互式Postgres会话。

sudo -u postgres psql

你将得到一个PostgreSQL提示,在这里你可以设置我们的要求。

首先,为你的项目创建一个数据库。

CREATE DATABASE myproject;

注意:每个Postgres语句必须以分号结束,所以如果你遇到问题,请确保你的命令以分号结束。

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

CREATE USER myprojectuser WITH PASSWORD 'password';

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

你将设置默认的字符编码为UTF-8 ,这是Django所期望的。你还将默认的事务隔离方案设置为 "read committed",这将阻止对未提交的事务的读取。最后,你要设置时区。默认情况下,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需求。

首先,创建并切换到一个可以保存项目文件的目录。

mkdir ~/myprojectdir
cd ~/myprojectdir

在项目目录中,通过输入以下内容创建一个 Python 虚拟环境。

python3 -m venv myprojectenv

这将创建一个名为 myprojectenv的目录。 myprojectdir目录。在里面,它将安装一个本地版本的Python和一个本地版本的pip 来管理软件包。你可以使用这个虚拟环境结构,为你想创建的任何项目安装和配置一个孤立的 Python 环境。

在安装项目的 Python 需求之前,你需要激活这个虚拟环境。你可以通过键入来完成。

source myprojectenv/bin/activate

你的提示应该改变,以表明你现在是在一个 Python 虚拟环境中操作。它看起来会像这样。 (myprojectenv)user@host:~/myprojectdir$.

在你的虚拟环境被激活后,安装Django、Gunicorn和psycopg2 PostgreSQL适配器,使用pip 的本地实例。

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

pip install django gunicorn psycopg2-binary

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

创建和配置一个新的 Django 项目

安装了Python组件后,现在可以创建实际的Django项目文件了。

创建Django项目

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

django-admin startproject myproject ~/myprojectdir

在这一点上,你的项目目录 (~/myprojectdir在这个例子中)应该有以下内容。

  • ~/myprojectdir/manage.py:一个 Django 项目管理脚本。
  • ~/myprojectdir/myproject/:Django项目包。这应该包含__init__.py,settings.py,urls.py,asgi.py, 和wsgi.py 文件。
  • ~/myprojectdir/myprojectenv/:你之前创建的虚拟环境目录。

调整项目设置

对于新创建的项目文件,你应该做的第一件事就是调整设置。使用nano 或你喜欢的文本编辑器打开设置文件。

nano ~/myprojectdir/myproject/settings.py

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

在方括号内,列出与你的Django服务器相关的IP地址或域名。每项内容都应该用引号列出,条目之间用逗号隔开。如果你希望对整个域和任何子域提出请求,请在条目的开头加上一个句号。在下面的片段中,有几个注释过的例子用于演示。

注意:请确保将localhost 作为选项之一,因为你将通过本地Nginx实例来代理连接。

~/myprojectdir/myproject/settings.py

. . .
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']

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

用你的PostgreSQL数据库信息改变设置。你告诉Django使用你用pip 安装的psycopg2 适配器。你需要给出数据库名称、数据库用户名、数据库用户的密码,然后指定数据库位于本地计算机上。你可以把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/'

# 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/')

完成后保存并关闭该文件。如果你使用的是nano ,按Ctrl+X ,然后在提示下按Y ,然后回车。

完成初始项目设置

现在,你可以使用管理脚本将初始数据库模式迁移到我们的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 index page

如果你在地址栏中的URL末尾加上/admin ,你会被提示输入你用createsuperuser 命令创建的管理用户名和密码。

Django admin login

在认证之后,你可以访问默认的Django管理界面。

Django admin interface

当你完成探索后,在终端窗口点击CTRL-C来关闭开发服务器。

测试Gunicorn为项目服务的能力

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

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

这将在Django开发服务器所运行的相同界面上启动Gunicorn。你可以回去在你的浏览器中再次测试这个应用程序。

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

你通过指定Django的wsgi.py 文件的相对目录路径传递给Gunicorn一个模块,该文件是你应用程序的入口,使用Python的模块语法。在这个文件里面,定义了一个叫做application 的函数,它被用来与应用程序进行通信。

当你完成测试后,在终端窗口点击CTRL-C来停止Gunicorn。

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

deactivate

你的提示符中的虚拟环境指示灯将被移除。

为 Gunicorn 创建 systemd Socket 和服务文件

你已经测试了Gunicorn可以与我们的Django应用程序进行交互,但你现在应该实现一种更强大的方式来启动和停止应用程序服务器。为了达到这个目的,你要制作systemd服务和套接字文件。

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

首先,以sudo 的权限为 Gunicorn 创建并打开一个 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 服务文件。服务文件的名称应与 socket 文件的名称一致,但扩展名除外。

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

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

检查Gunicorn套接字文件的情况

检查进程的状态,了解它是否能够启动。

sudo systemctl status gunicorn.socket

你应该收到类似这样的输出。

Output
 gunicorn.socket - gunicorn socket
     Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled)
     Active: active (listening) since Thu 2022-08-04 19:02:54 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.

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

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)
TriggeredBy:  gunicorn.socket

为了测试套接字的激活机制,你可以通过键入curl ,向套接字发送一个连接。

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

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

sudo systemctl status gunicorn
Outputgunicorn.service - gunicorn daemon
     Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-08-04 19:03:51 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"

如果来自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忽略任何寻找favicon的问题。你还要告诉它,在哪里可以找到你收集的静态资产,在你的 ~/myprojectdir/static目录中的静态资产。所有这些文件都有一个标准的URI前缀"/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 / {} 块,以匹配所有其他请求。在这个位置,你将包含Nginx安装时的标准proxy_params 文件,然后将流量直接传递给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来保证服务器的流量安全。这很重要,因为如果没有它,所有的信息,包括密码都是以纯文本形式在网络上发送。

如果你有一个域名,最直接的方法是使用Let's Encrypt来获得SSL证书,以保证你的流量。按照本指南,在Debian 11上用Nginx设置Let's Encrypt。使用本指南中创建的Nginx服务器块,按照该程序操作。

排除Nginx和Gunicorn的故障

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

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

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

Nginx使用server_name 来决定使用哪个服务器块来响应请求。如果你收到的是Nginx的默认页面,这表明Nginx无法将请求明确匹配到一个服务器块,所以它回到了/etc/nginx/sites-available/default 中定义的默认块。

你项目中的服务器块server_name ,必须比默认服务器块中的更具体,才能被选中。

Nginx显示502坏网关错误,而不是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 文件。你应该比较/etc/nginx/sites-available/myproject 文件中定义的proxy_pass 位置和gunicorn.socket systemd单元生成的gunicorn.sock 文件的实际位置。

如果在/run 目录中找不到gunicorn.sock 文件,通常意味着 systemd socket 文件无法创建该文件。回到检查Gunicorn套接字文件的章节,逐步了解Gunicorn的故障排除步骤。

connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

这表明Nginx因为权限问题而无法连接到Gunicorn套接字。当使用根用户而不是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

输出显示每个目录组件的权限。通过查看权限(第一列)、所有者(第二列)和组所有者(第三列),你可以弄清楚允许对socket文件进行什么类型的访问。

在上面的例子中,socket文件和通往socket文件的每个目录都有世界范围内的读取和执行权限(目录的权限栏以r-x 结尾,而不是--- )。Nginx进程应该能够成功访问该套接字。

如果通往套接字的任何目录没有世界读取和执行的权限,Nginx将无法访问套接字,除非允许世界读取和执行的权限,或者确保组的所有权被赋予Nginx所属的组。

Django显示。"could not connect to server:连接被拒绝"

当你试图在网络浏览器中访问应用程序的某些部分时,你可能会从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通过提供许多常见的部分来帮助创建项目和应用程序,使你能够专注于独特的元素。通过利用本文描述的一般工具链,你可以从一个服务器上为你创建的应用程序提供服务。