介绍
Django是一个功能强大的网络框架,可以帮助您启动Python应用程序或网站。Django包括一个简化的开发服务器,用于在本地测试您的代码,但是对于任何与生产无关的事情,都需要一个更安全,功能更强大的Web服务器。
在本指南中,我们将演示如何在Ubuntu 16.04上安装和配置一些组件以支持和服务Django应用程序。我们将建立一个PostgreSQL数据库,而不是使用默认的SQLite数据库。我们将配置Gunicorn应用程序服务器以与我们的应用程序接口。然后,我们将设置Nginx来反向代理Gunicorn,从而使我们能够使用其安全性和性能功能来服务我们的应用程序。
先决条件和目标
为了完成本指南,您应该具有一个全新的Ubuntu 16.04服务器实例,该实例具有sudo
配置了特权的非root用户。
我们将在虚拟环境中安装Django。将Django安装到特定于您的项目的环境中将使您的项目及其要求可以分别处理。
一旦数据库和应用程序启动并运行,我们将安装和配置Gunicorn应用程序服务器。这将用作我们应用程序的接口,将HTTP中的客户端请求转换为我们的应用程序可以处理的Python调用。然后,我们将在Gunicorn前面设置Nginx,以利用其高性能的连接处理机制和易于实现的安全功能。
让我们开始吧。
从Ubuntu存储库安装软件包
要开始此过程,我们将从Ubuntu存储库中下载并安装所需的所有项目。稍后,我们将使用Python软件包管理器pip
安装其他组件。
我们需要更新本地apt
软件包索引,然后下载并安装软件包。我们安装的软件包取决于您的项目将使用哪个Python版本。
如果您使用的是Python 2,请输入:
sudo apt-get update
sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx
复制
sudo apt-get update
sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
复制
这将安装pip
,以后构建Gunicorn所需的Python开发文件,Postgres数据库系统和与其进行交互所需的库以及Nginx Web服务器。
创建PostgreSQL数据库和用户
我们将直接进入并为Django应用程序创建数据库和数据库用户。
默认情况下,Postgres对本地连接使用一种称为“对等身份验证”的身份验证方案。基本上,这意味着如果用户的操作系统用户名与有效的Postgres用户名匹配,则该用户无需进一步的身份验证即可登录。
在安装Postgres的过程中,postgres
创建了一个名为的操作系统用户,以与postgres
PostgreSQL管理用户相对应。我们需要使用该用户来执行管理任务。我们可以使用sudo并使用-u选项传递用户名。
通过键入以下内容来登录交互式Postgres会话:
sudo -u postgres psql
复制
您将看到一个PostgreSQL提示,我们可以在其中设置我们的要求。
首先,为您的项目创建一个数据库:
CREATE DATABASE myproject;
复制
注意
每个Postgres语句都必须以分号结尾,因此如果遇到问题,请确保命令以1结尾。
接下来,为我们的项目创建一个数据库用户。确保选择一个安全密码:
CREATE USER myprojectuser WITH PASSWORD 'password';
复制
之后,我们将为刚刚创建的用户修改一些连接参数。这将加速数据库操作,从而不必在每次建立连接时都查询和设置正确的值。
我们将Django期望的默认编码设置为UTF-8。我们还将默认事务隔离方案设置为“读已提交”,该方案将阻止未提交事务的读取。最后,我们设置时区。默认情况下,我们的Django项目将设置为use UTC
。这些都是建议:
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
复制
为您的项目创建Python虚拟环境
现在我们有了数据库,我们可以开始准备其余的项目需求。我们将在虚拟环境中安装Python要求,以简化管理。
为此,我们首先需要访问该virtualenv
命令。我们可以使用安装它pip
。
如果您使用的是Python 2,pip
请输入以下内容来升级和安装软件包:
sudo -H pip install --upgrade pip
sudo -H pip install virtualenv
复制
如果您使用的是Python 3,pip
请输入以下命令来升级和安装软件包:
sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv
复制
随着virtualenv
安装,我们可以开始形成我们的项目。创建并移至一个目录,我们可以在其中保存项目文件:
mkdir ~/myproject
cd ~/myproject
复制
在项目目录中,通过键入以下内容来创建Python虚拟环境:
virtualenv myprojectenv
复制
这将myprojectenv
在您的myproject
目录中创建一个目录。在内部,它将安装Python的本地版本和的本地版本pip
。我们可以使用它为我们的项目安装和配置一个隔离的Python环境。
在安装项目的Python要求之前,我们需要激活虚拟环境。您可以通过输入以下内容来实现:
source myprojectenv/bin/activate
复制
您的提示应更改为指示您现在在Python虚拟环境中进行操作。看起来像这样:。(myprojectenv)user@host:~/myproject$
在您的虚拟环境处于活动状态psycopg2
的情况下,使用以下本地实例安装Django,Gunicorn和PostgreSQL适配器pip
:
注意
无论使用哪种版本的Python,在激活虚拟环境时,都应使用pip
命令(不是pip3
)。
pip install django gunicorn psycopg2
复制
现在,您应该拥有启动Django项目所需的所有软件。
创建和配置新的Django项目
安装我们的Python组件后,我们可以创建实际的Django项目文件。
创建Django项目
由于我们已经有一个项目目录,因此我们将告诉Django在此处安装文件。它将使用正常的代码创建第二级目录,并将其放置在该目录中。这样做的关键是我们正在明确定义目录,而不是允许Django相对于当前目录做出决定:
django-admin.py startproject myproject ~/myproject
复制
此时,您的项目目录(在我们的情况下)应具有以下内容:~/myproject
~/myproject/manage.py
:Django项目管理脚本。~/myproject/myproject/
:Django项目包。这应该包括__init__.py
,settings.py
,urls.py
,和wsgi.py
文件。~/myproject/myprojectenv/
:我们之前创建的虚拟环境目录。
调整项目设置
我们对新创建的项目文件应该做的第一件事是调整设置。在文本编辑器中打开设置文件:
nano ~/myproject/myproject/settings.py
首先找到ALLOWED_HOSTS
指令。这定义了服务器地址或域名的列表,可用于连接到Django实例。带有不在此列表中的Host标头的任何传入请求都将引发异常。Django要求您对此进行设置,以防止出现某类安全漏洞。
在方括号中,列出与Django服务器关联的IP地址或域名。每个项目都应以引号列出,各条目之间用逗号分隔。如果希望请求整个域和任何子域,请在条目的开头加上句点。在以下代码段中,有一些注释掉的示例用于演示:
〜/ myproject / myproject / settings.py
<span style="color:#333333"><span style="color:#545454"><code class="language-bash"><span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span>
<span style="color:#808591"># The simplest case: just add the domain name(s) and IP addresses of your Django server</span>
<span style="color:#808591"># ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']</span>
<span style="color:#808591"># To respond to 'example.com' and any subdomains, start the domain with a dot</span>
<span style="color:#808591"># ALLOWED_HOSTS = ['.example.com', '203.0.113.5']</span>
ALLOWED_HOSTS <span style="color:#666a71">=</span> <span style="color:#666a71">[</span><span style="color:#08966b">'<span style="color:inherit">your_server_domain_or_IP</span>'</span>, <span style="color:#08966b">'<span style="color:inherit">second_domain_or_IP</span>'</span>, <span style="color:inherit"><span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span> .</span><span style="color:#666a71">]</span></code></span></span>
接下来,找到配置数据库访问的部分。它将从开始DATABASES
。该文件中的配置适用于SQLite数据库。我们已经为我们的项目创建了一个PostgreSQL数据库,因此我们需要调整设置。
使用PostgreSQL数据库信息更改设置。我们告诉Django使用psycopg2
我们安装的适配器pip
。我们需要提供数据库名称,数据库用户名,数据库用户的密码,然后指定数据库位于本地计算机上。您可以将PORT
设置保留为空字符串:
〜/ myproject / myproject / settings.py
<span style="color:#333333"><span style="color:#545454"><code class="language-bash"><span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span>
DATABASES <span style="color:#666a71">=</span> <span style="color:#666a71">{</span>
<span style="color:#08966b">'default'</span><span style="color:#e0276a">:</span> <span style="color:#666a71">{</span>
<span style="color:#08966b">'ENGINE'</span><span style="color:#e0276a">:</span> <span style="color:#08966b">'django.db.backends.<span style="color:inherit">postgresql_psycopg2</span>'</span>,
<span style="color:#08966b">'NAME'</span><span style="color:#e0276a">:</span> <span style="color:#08966b">'<span style="color:inherit">myproject</span>'</span>,
<span style="color:#08966b">'USER'</span><span style="color:#e0276a">:</span> <span style="color:#08966b">'<span style="color:inherit">myprojectuser</span>'</span>,
<span style="color:#08966b">'PASSWORD'</span><span style="color:#e0276a">:</span> <span style="color:#08966b">'<span style="color:inherit">password</span>'</span>,
<span style="color:#08966b">'HOST'</span><span style="color:#e0276a">:</span> <span style="color:#08966b">'localhost'</span>,
<span style="color:#08966b">'PORT'</span><span style="color:#e0276a">:</span> <span style="color:#08966b">''</span>,
<span style="color:#666a71">}</span>
<span style="color:#666a71">}</span>
<span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span></code></span></span>
复制
接下来,向下移动到文件底部,并添加一个指示应将静态文件放置在何处的设置。这是必需的,以便Nginx可以处理对这些项目的请求。以下行告诉Django将它们放置static
在基础项目目录中的目录中:
〜/ myproject / myproject / settings.py
<span style="color:#333333"><span style="color:#545454"><code class="language-bash"><span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span> <span style="color:#e0276a">.</span>
STATIC_URL <span style="color:#666a71">=</span> <span style="color:#08966b">'/static/'</span>
<span style="color:inherit">STATIC_ROOT <span style="color:#666a71">=</span> os.path.join<span style="color:#666a71">(</span>BASE_DIR, <span style="color:#08966b">'static/'</span><span style="color:#666a71">)</span></span></code></span></span>
复制
完成后保存并关闭文件。
完成初始项目设置
现在,我们可以使用管理脚本将初始数据库架构迁移到PostgreSQL数据库:
~/myproject/manage.py makemigrations
~/myproject/manage.py migrate
复制
通过键入以下内容为项目创建一个管理用户:
~/myproject/manage.py createsuperuser
复制
您将必须选择一个用户名,提供一个电子邮件地址,然后选择并确认密码。
我们可以通过键入以下命令将所有静态内容收集到我们配置的目录位置中:
~/myproject/manage.py collectstatic
复制
您必须确认操作。然后,这些静态文件将放置在static
项目目录内的目录中。
如果您遵循初始服务器设置指南,则应该具有UFW防火墙来保护服务器。为了测试开发服务器,我们必须允许访问将要使用的端口。
通过键入以下内容为端口8000创建一个例外:
sudo ufw allow 8000
复制
最后,您可以通过使用以下命令启动Django开发服务器来测试我们的项目:
~/myproject/manage.py runserver 0.0.0.0:8000
复制
在您的Web浏览器中,访问服务器的域名或IP地址,然后输入:8000
:
<span style="color:#545454"><code>http://<span style="color:inherit">server_domain_or_IP</span>:8000
</code></span>
您应该看到默认的Django索引页面:
如果/admin
在地址栏中追加到URL的末尾,将提示您输入使用以下createsuperuser
命令创建的管理用户名和密码:
验证之后,您可以访问默认的Django管理界面:
探索完成后,请在终端窗口中按CTRL-C以关闭开发服务器。
测试Gunicorn服务项目的能力
在离开虚拟环境之前,我们要做的最后一件事是测试Gunicorn,以确保它可以为应用程序提供服务。我们可以通过输入项目目录并使用gunicorn
来加载项目的WSGI模块来做到这一点:
cd ~/myproject
gunicorn --bind 0.0.0.0:8000 myproject.wsgi
复制
这将在运行Django开发服务器的同一界面上启动Gunicorn。您可以返回并再次测试该应用。
注意:由于Gunicorn不了解负责此操作的静态CSS内容,因此管理界面将不会应用任何样式。
我们通过wsgi.py
使用Python的模块语法指定Django文件的相对目录路径(这是我们应用程序的入口点)来为Gunicorn传递模块。在此文件内部,application
定义了一个名为的函数,该函数用于与应用程序进行通信。
完成测试后,在终端窗口中按CTRL-C停止Gunicorn。
现在,我们完成了Django应用程序的配置。我们可以通过键入以下内容退出虚拟环境:
deactivate
复制
提示中的虚拟环境指示器将被删除。
创建一个Gunicorn systemd服务文件
我们已经测试了Gunicorn可以与我们的Django应用程序交互,但是我们应该实现一种更强大的启动和停止应用程序服务器的方式。为此,我们将制作一个systemd服务文件。
使用sudo
文本编辑器中的权限为Gunicorn创建并打开systemd服务文件:
sudo nano /etc/systemd/system/gunicorn.service
从此[Unit]
部分开始,该部分用于指定元数据和相关性。我们将在此处对服务进行描述,并告诉init系统仅在达到网络目标后才启动此服务:
/etc/systemd/system/gunicorn.service
<span style="color:#333333"><span style="color:#545454"><code class="language-bash"><span style="color:#666a71">[</span>Unit<span style="color:#666a71">]</span>
<span style="color:#08966b">Description</span><span style="color:#666a71">=</span>gunicorn daemon
<span style="color:#08966b">After</span><span style="color:#666a71">=</span>network.target</code></span></span>
复制
接下来,我们将打开该[Service]
部分。我们将指定要处理的用户和组。由于该过程拥有所有相关文件,因此我们将授予该过程的常规用户帐户所有权。我们将把组所有权授予该www-data
组,以便Nginx可以轻松地与Gunicorn进行通信。
然后,我们将映射出工作目录并指定用于启动服务的命令。在这种情况下,我们必须指定Gunicorn可执行文件的完整路径,该路径已安装在虚拟环境中。由于Nginx安装在同一台计算机上,因此我们将其绑定到项目目录中的Unix套接字。这比使用网络端口更安全,更快捷。我们还可以在此处指定任何可选的Gunicorn调整项。例如,在这种情况下,我们指定了3个工作进程:
/etc/systemd/system/gunicorn.service
<span style="color:#333333"><span style="color:#545454"><code class="language-bash"><span style="color:#666a71">[</span>Unit<span style="color:#666a71">]</span>
<span style="color:#08966b">Description</span><span style="color:#666a71">=</span>gunicorn daemon
<span style="color:#08966b">After</span><span style="color:#666a71">=</span>network.target
<span style="color:#666a71">[</span>Service<span style="color:#666a71">]</span>
<span style="color:#08966b">User</span><span style="color:#666a71">=</span><span style="color:inherit">sammy</span>
<span style="color:#08966b">Group</span><span style="color:#666a71">=</span>www-data
<span style="color:#08966b">WorkingDirectory</span><span style="color:#666a71">=</span>/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>
<span style="color:#08966b">ExecStart</span><span style="color:#666a71">=</span>/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>/<span style="color:inherit">myprojectenv</span>/bin/gunicorn --access-logfile - --workers <span style="color:#225196">3</span> --bind unix:/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>/<span style="color:inherit">myproject</span>.sock myproject.wsgi:application</code></span></span>
复制
最后,我们将添加一个[Install]
部分。如果我们启用该服务以在启动时启动,它将告诉systemd该服务链接到什么。我们希望该服务在常规多用户系统启动并运行时启动:
/etc/systemd/system/gunicorn.service
<span style="color:#333333"><span style="color:#545454"><code class="language-bash"><span style="color:#666a71">[</span>Unit<span style="color:#666a71">]</span>
<span style="color:#08966b">Description</span><span style="color:#666a71">=</span>gunicorn daemon
<span style="color:#08966b">After</span><span style="color:#666a71">=</span>network.target
<span style="color:#666a71">[</span>Service<span style="color:#666a71">]</span>
<span style="color:#08966b">User</span><span style="color:#666a71">=</span><span style="color:inherit">sammy</span>
<span style="color:#08966b">Group</span><span style="color:#666a71">=</span>www-data
<span style="color:#08966b">WorkingDirectory</span><span style="color:#666a71">=</span>/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>
<span style="color:#08966b">ExecStart</span><span style="color:#666a71">=</span>/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>/<span style="color:inherit">myprojectenv</span>/bin/gunicorn --access-logfile - --workers <span style="color:#225196">3</span> --bind unix:/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>/<span style="color:inherit">myproject</span>.sock myproject.wsgi:application
<span style="color:#666a71">[</span>Install<span style="color:#666a71">]</span>
<span style="color:#08966b">WantedBy</span><span style="color:#666a71">=</span>multi-user.target</code></span></span>
复制
这样,我们的systemd服务文件就完成了。立即保存并关闭它。
现在,我们可以启动我们创建的Gunicorn服务并启用它,以便它在启动时启动:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
复制
我们可以通过检查套接字文件来确认操作成功。
检查Gunicorn套接字文件
检查进程的状态,以了解它是否能够启动:
sudo systemctl status gunicorn
复制
接下来,检查myproject.sock
项目目录中是否存在该文件:
ls /home/sammy/myproject
复制
Output
manage.py myproject myprojectenv myproject.sock static
如果systemctl status
命令指示发生错误,或者您myproject.sock
在目录中找不到该文件,则表明Gunicorn无法正确启动。通过输入以下命令检查Gunicorn进程日志:
sudo journalctl -u gunicorn
复制
查看日志中的消息,找出Gunicorn遇到问题的地方。您可能会遇到问题的原因有很多,但是通常,如果Gunicorn无法创建套接字文件,则是由于以下原因之一:
- 项目文件归
root
用户所有,而不是sudo
用户所有 - 文件中的
WorkingDirectory
路径/etc/systemd/system/gunicorn.service
未指向项目目录 - 指令中为
gunicorn
进程指定的配置选项ExecStart
不正确。检查以下项目:gunicorn
二进制文件的路径指向虚拟环境中二进制文件的实际位置- 该
--bind
指令定义了要在Gunicorn可以访问的目录中创建的文件 - 这
myproject.wsgi:application
是可调用WSGI的准确路径。这意味着当您进入时WorkingDirectory
,您应该能够application
通过在myproject.wsgi
模块中查找来调用可调用的名称(该模块可转换为名为的文件./myproject/wsgi.py
)
如果对/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
<span style="color:#333333"><span style="color:#545454"><code class="language-bash">server <span style="color:#666a71">{</span>
listen <span style="color:#225196">80</span><span style="color:#666a71">;</span>
server_name <span style="color:inherit">server_domain_or_IP</span><span style="color:#666a71">;</span>
<span style="color:#666a71">}</span></code></span></span>
复制
接下来,我们将告诉Nginx忽略查找收藏夹图标的任何问题。我们还将告诉它在哪里可以找到我们在目录中收集的静态资产。所有这些文件的标准URI前缀均为“ / static”,因此我们可以创建一个位置块来匹配这些请求:~/myproject/static
/ etc / nginx / sites-available / myproject
<span style="color:#333333"><span style="color:#545454"><code class="language-bash">server <span style="color:#666a71">{</span>
listen <span style="color:#225196">80</span><span style="color:#666a71">;</span>
server_name <span style="color:inherit">server_domain_or_IP</span><span style="color:#666a71">;</span>
location <span style="color:#666a71">=</span> /favicon.ico <span style="color:#666a71">{</span> access_log off<span style="color:#666a71">;</span> log_not_found off<span style="color:#666a71">;</span> <span style="color:#666a71">}</span>
location /static/ <span style="color:#666a71">{</span>
root /home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span><span style="color:#666a71">;</span>
<span style="color:#666a71">}</span>
<span style="color:#666a71">}</span></code></span></span>
复制
最后,我们将创建一个location / {}
块以匹配所有其他请求。在此位置的内部,我们将包括proxy_params
Nginx安装中包含的标准文件,然后将流量传递给Gunicorn进程创建的套接字:
/ etc / nginx / sites-available / myproject
<span style="color:#333333"><span style="color:#545454"><code class="language-bash">server <span style="color:#666a71">{</span>
listen <span style="color:#225196">80</span><span style="color:#666a71">;</span>
server_name <span style="color:inherit">server_domain_or_IP</span><span style="color:#666a71">;</span>
location <span style="color:#666a71">=</span> /favicon.ico <span style="color:#666a71">{</span> access_log off<span style="color:#666a71">;</span> log_not_found off<span style="color:#666a71">;</span> <span style="color:#666a71">}</span>
location /static/ <span style="color:#666a71">{</span>
root /home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span><span style="color:#666a71">;</span>
<span style="color:#666a71">}</span>
location / <span style="color:#666a71">{</span>
include proxy_params<span style="color:#666a71">;</span>
proxy_pass http://unix:/home/<span style="color:inherit">sammy</span>/<span style="color:inherit">myproject</span>/<span style="color:inherit">myproject</span>.sock<span style="color:#666a71">;</span>
<span style="color:#666a71">}</span>
<span style="color:#666a71">}</span></code></span></span>
复制
完成后保存并关闭文件。现在,我们可以通过将文件链接到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证书以确保流量安全的最简单方法是使用“加密”。按照本指南在Ubuntu 16.04上设置“使用Nginx加密”。
如果您没有域名,您仍然可以使用自签名SSL证书保护您的网站以进行测试和学习。
对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
项目服务器块中的in必须比要选择的默认服务器块中的特定。
Nginx显示502 Bad Gateway错误,而不是Django应用程序
502错误表示Nginx无法成功代理请求。各种各样的配置问题都以502错误表示,因此需要更多信息以进行适当的故障排除。
寻找更多信息的主要地方是在Nginx的错误日志中。通常,这将告诉您什么情况在代理事件期间导致了问题。通过输入以下内容来关注Nginx错误日志:
sudo tail -F /var/log/nginx/error.log
复制
现在,在浏览器中再次发出请求以生成新的错误(尝试刷新页面)。您应该看到一条新的错误消息写入日志。如果您查看此消息,它应该可以帮助您缩小问题范围。
您可能会看到以下消息:
connect()到unix:/home/sammy/myproject/myproject.sock失败(2:没有这样的文件或目录)
这表明Nginxmyproject.sock
在给定位置找不到文件。您应该将文件中proxy_pass
定义/etc/nginx/sites-available/myproject
的位置与myproject.sock
项目目录中生成的文件的实际位置进行比较。
如果myproject.sock
在项目目录中找不到文件,则通常表示该gunicorn
进程无法创建该文件。返回有关检查Gunicorn套接字文件的部分,以逐步完成Gunicorn的故障排除步骤。
connect()到unix:/home/sammy/myproject/myproject.sock失败(13:权限被拒绝)
这表明由于权限问题,Nginx无法连接到Gunicorn套接字。通常,在使用root用户而不是root用户执行该过程时会发生这种情况sudo
。尽管Gunicorn进程能够创建套接字文件,但Nginx无法访问它。
如果/
在myproject.sock
文件的根目录()之间的任何位置都有有限的权限,则会发生这种情况。通过将套接字文件的绝对路径传递给namei
命令,我们可以查看套接字文件及其每个父目录的权限和所有权值:
namei -nom /home/sammy/myproject/myproject.sock
复制
Output
f: /home/sammy/myproject/myproject.sock drwxr-xr-x root root / drwxr-xr-x root root home drwxr-xr-x sammy sammy sammy drwxrwxr-x sammy sammy myproject srwxrwxrwx sammy www-data myproject.sock
输出显示每个目录组件的权限。通过查看权限(第一列),所有者(第二列)和组所有者(第三列),我们可以确定允许对套接字文件进行哪种类型的访问。
在上面的示例中,套接字文件和通向该套接字文件的每个目录都具有世界范围的读取和执行权限(目录的权限列以r-x
而不是结束---
)。Nginx进程应该能够成功访问套接字。
如果通向套接字的任何目录都不具有世界范围的读取和执行许可权,则Nginx将无法在没有世界范围的读取和执行许可权或确保将组所有权授予Nginx所属的组的情况下访问套接字的。对于/root
目录等敏感位置,以上两个选项都是危险的。最好将项目文件移到目录之外,您可以在其中安全地控制访问而不损害安全性。
Django正在显示:“无法连接到服务器:连接被拒绝”
尝试在Web浏览器中访问应用程序的某些部分时,您可能会从Django中看到一条消息:
<span style="color:#545454"><code>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?
</code></span>
这表明Django无法连接到Postgres数据库。通过键入以下命令来确保Postgres实例正在运行:
sudo systemctl status postgresql
复制
如果不是,则可以输入以下命令来启动它并使它能够在启动时自动启动(如果尚未配置):
sudo systemctl start postgresql
sudo systemctl enable postgresql
复制
如果仍然有问题,请确保~/myproject/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
在更新配置或应用程序时,可能需要重新启动过程以适应您的更改。
如果更新Django应用程序,则可以通过键入以下内容重新启动Gunicorn进程以获取更改:
sudo systemctl restart gunicorn
复制
如果更改gunicorn
systemd服务文件,请重新输入守护程序并通过键入以下内容重新启动该过程:
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
复制
如果更改Nginx服务器块配置,请通过以下命令测试配置,然后测试Nginx:
sudo nginx -t && sudo systemctl restart nginx
复制
这些命令有助于您在调整配置时获取更改。
结论
在本指南中,我们在其自己的虚拟环境中设置了一个Django项目。我们已经配置了Gunicorn来翻译客户端请求,以便Django可以处理它们。之后,我们将Nginx设置为充当反向代理,以处理客户端连接并根据客户端请求提供正确的项目。
Django提供了许多常见的部分,使您可以专注于独特的元素,从而使创建项目和应用程序变得简单。通过利用本文介绍的常规工具链,您可以轻松地为从单个服务器创建的应用程序提供服务。