介绍
Django 是一个强大的 Web 框架,可以帮助您将您的 Python 应用程序或网站从地面上获得。Django 包含一个简化开发服务器来本地测试您的代码,但对于任何与生产有关的内容,需要一个更安全、更强大的 Web 服务器。
在本指南中,我们将展示如何在Ubuntu 16.04上安装和配置某些组件以支持和服务Django应用程序。我们将设置一个PostgreSQL数据库,而不是使用默认的SQLite数据库。我们将配置Gunicorn应用程序服务器与我们的应用程序进行交互。
前提和目标
为了完成本指南,您应该有一个新的Ubuntu 16.04服务器实例,具有非根用户的sudo
特权配置,您可以通过我们的 初始服务器设置指南来学习如何设置此设置。
将 Django 安装在虚拟环境中,而将 Django 安装在您项目的特定环境中,将使您的项目及其需求能够单独处理。
一旦我们的数据库和应用程序启动并运行,我们将安装和配置Gunicorn应用程序服务器,这将作为我们的应用程序的界面,将客户端请求翻译成HTTP到我们的应用程序可以处理的Python呼叫。
让我们开始吧。
安装 Ubuntu 存储库中的软件包
要开始这个过程,我们将从Ubuntu存储库下载并安装我们需要的所有项目,我们将使用Python包管理器pip
稍后安装额外的组件。
我们需要更新本地apt
包索引,然后下载和安装包. 我们安装的包取决于您的项目将使用哪个版本的Python。
如果您正在使用 Python 2,请键入:
1sudo apt-get update
2sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx
如果您正在使用 Django 和 Python 3,请键入:
1sudo apt-get update
2sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
這將安裝「pip」,後來建立 Gunicorn 所需的 Python 開發檔案、Postgres 資料庫系統和與之互動所需的圖書館,以及 Nginx 網頁伺服器。
创建 PostgreSQL 数据库和用户
我们将直接跳进并为我们的Django应用程序创建一个数据库和数据库用户。
默认情况下,Postgres 使用一个名为对等身份验证
的身份验证方案进行本地连接,这基本上意味着如果用户的操作系统用户名匹配一个有效的Postgres 用户名,则该用户可以无需进一步身份验证登录。
在 Postgres 安装过程中,一个名为postgres
的操作系统用户被创建,以匹配postgres
的 PostgreSQL 管理用户。我们需要使用这个用户来执行管理任务。
通过键入登录到一个互动的 Postgres 会话:
1sudo -u postgres psql
您将收到一个PostgreSQL提示,我们可以设置我们的要求。
首先,为您的项目创建一个数据库:
1CREATE DATABASE myproject;
<$>[注] [标签注] 每个 Postgres 语句都必须以半列结束,因此如果您遇到问题,请确保您的命令以一个结束。
接下来,为我们的项目创建一个数据库用户. 请确保选择安全密码:
1CREATE USER myprojectuser WITH PASSWORD 'password';
之后,我们将对我们刚刚创建的用户修改一些连接参数,这将加快数据库操作,以便每次建立连接时不需要查询和设置正确的值。
我们正在将默认编码设置为 UTF-8,这也是 Django 所期望的。我们还将默认的交易隔离方案设置为读取承诺
,即从未承诺的交易中读取块。最后,我们正在设置时区。
1ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
2ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
3ALTER ROLE myprojectuser SET timezone TO 'UTC';
现在,我们可以为我们的新用户提供访问权限来管理我们的新数据库:
1GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
完成后,通过键入退出 PostgreSQL 提示:
1\q
为您的项目创建一个Python虚拟环境
现在我们有我们的数据库,我们可以开始准备剩余的项目要求,我们将在虚拟环境中安装我们的Python要求,以便更容易管理。
要做到这一点,我们首先需要访问virtualenv
命令,我们可以使用pip
来安装它。
如果您正在使用 Python 2,请通过键入以下方式升级pip
并安装该包:
1sudo -H pip install --upgrade pip
2sudo -H pip install virtualenv
如果您正在使用 Python 3,请通过键入以下方式升级pip
并安装该包:
1sudo -H pip3 install --upgrade pip
2sudo -H pip3 install virtualenv
安装了virtualenv
,我们可以开始创建我们的项目,并移动到一个目录,我们可以保留我们的项目文件:
1mkdir ~/myproject
2cd ~/myproject
在项目目录中,通过键入创建一个Python虚拟环境:
1virtualenv myprojectenv
这将创建一个名为myprojectenv
的目录在你的myproject
目录中。内部,它将安装一个本地版本的Python和一个本地版本的pip
。
在我们安装项目的 Python 要求之前,我们需要激活虚拟环境,您可以通过键入:
1source myprojectenv/bin/activate
您的提示应更改,以表示您现在在Python虚拟环境中运行,它将看起来像这样: (myprojectenv)user@host:~/myproject$
。
随着虚拟环境的启动,安装 Django、Gunicorn 和psycopg2
PostgreSQL 适配器,使用本地实例pip
:
<$>[注]
[标签注]
无论您正在使用哪个版本的 Python,当虚拟环境被激活时,您应该使用pip
命令(而不是pip3
)。
1pip install django gunicorn psycopg2
您现在应该拥有启动 Django 项目所需的所有软件。
创建和配置一个新的Django项目
有了我们的Python组件安装,我们可以创建实际的Django项目文件。
创建 Django 项目
由于我们已经有一个项目目录,我们会告诉Django在这里安装文件,它将创建一个与实际代码的第二级目录,这是正常的,并在这个目录中放置一个管理脚本。
1django-admin.py startproject myproject ~/myproject
在此时,您的项目目录(在我们的情况下,~/myproject
)应该有以下内容:
~/myproject/manage.py
: 一个 Django 项目管理脚本.~/myproject/myproject/
: 该 Django 项目包. 这应该包含__init__.py
,settings.py
,urls.py
和wsgi.py
文件.~/myproject/myprojectenv/
: 以前我们创建的虚拟环境目录.
调整项目设置
我们应该做的第一件事与我们新创建的项目文件是调整设置. 在文本编辑器中打开设置文件:
1nano ~/myproject/myproject/settings.py
首先,找出「ALLOWED_HOSTS」指令,定义了服务器的地址或域名列表,可以用来连接到Django实例,任何未列入此列表的 Host标题的输入请求都会引发例外。
在方块中,列出与您的 Django 服务器相关的 IP 地址或域名。每个项目都应该列入引文中,其中有条纹分开的条目。如果您希望对整个域和任何子域的请求,请预先预设一个时间段,以便开始输入。在下面的片段中,有几个被评论的示例用于示范:
1[label ~/myproject/myproject/settings.py]
2. . .
3# The simplest case: just add the domain name(s) and IP addresses of your Django server
4# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
5# To respond to 'example.com' and any subdomains, start the domain with a dot
6# ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
7ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . .]
接下来,找到配置数据库访问的部分. 它将从DATABASES
开始. 文件中的配置是用于 SQLite 数据库. 我们已经为我们的项目创建了一个 PostgreSQL 数据库,所以我们需要调整设置。
使用您的 PostgreSQL 数据库信息更改设置. 我们告诉 Django 使用我们与pip
安装的psycopg2
适配器. 我们需要输入数据库名称、数据库用户名称、数据库用户密码,然后指定数据库位于本地计算机上。
1[label ~/myproject/myproject/settings.py]
2. . .
3
4DATABASES = {
5 'default': {
6 'ENGINE': 'django.db.backends.postgresql_psycopg2',
7 'NAME': 'myproject',
8 'USER': 'myprojectuser',
9 'PASSWORD': 'password',
10 'HOST': 'localhost',
11 'PORT': '',
12 }
13}
14
15. . .
接下来,移动到文件的底部,并添加一个设置,表示 static 文件应该放置在哪里。 这是必要的,以便 Nginx 能够处理这些项目的请求。
1[label ~/myproject/myproject/settings.py]
2. . .
3
4STATIC_URL = '/static/'
5STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
保存并关闭文件,当你完成。
完整的初始项目设置
现在,我们可以使用管理脚本将初始数据库方案迁移到我们的PostgreSQL数据库:
1~/myproject/manage.py makemigrations
2~/myproject/manage.py migrate
创建一个项目的管理用户,键入:
1~/myproject/manage.py createsuperuser
您将需要选择用户名,提供电子邮件地址,并选择并确认密码。
我们可以将所有静态内容收集到我们通过键入配置的目录位置:
1~/myproject/manage.py collectstatic
然后,静态文件将被放置在项目目录中的名为静态
的目录中。
如果您遵循最初的服务器设置指南,您应该有一个 UFW 防火墙来保护您的服务器. 为了测试开发服务器,我们必须允许访问我们将使用的端口。
通过键入为端口 8000 创建例外:
1sudo ufw allow 8000
最后,您可以通过使用以下命令启动 Django 开发服务器来测试我们的项目:
1~/myproject/manage.py runserver 0.0.0.0:8000
在您的 Web 浏览器中,访问您的服务器的域名或 IP 地址,然后是 :8000
:
1http://server_domain_or_IP:8000
您应该看到默认的 Django 索引页面:
如果您在地址栏中添加/admin
到URL的末尾,您将被提示使用createsuperuser
命令创建的管理用户名和密码:
验证后,您可以访问默认的 Django admin 界面:
当您完成探索时,请在终端窗口中按 CTRL-C 关闭开发服务器。
测试 Gunicorn 服务项目的能力
在离开我们的虚拟环境之前,我们要做的最后一件事是测试Gunicorn,以确保它能为应用程序提供服务。
1cd ~/myproject
2gunicorn --bind 0.0.0.0:8000 myproject.wsgi
这将启动Gunicorn在Django开发服务器正在运行的相同界面上,您可以返回并再次测试应用程序。
<$>[注] 注: 管理员界面将不会有任何的样式应用,因为Gunicorn不知道对此负责的静态CSS内容。
我们通过指定相对目录路径给Django的wsgi.py
文件,这是我们应用程序的入口点,使用Python的模块语法通过Gunicorn传递了一个模块。
当您完成测试时,请在终端窗口中按 CTRL-C 以阻止 Gunicorn。
我们现在已经完成了我们的Django应用程序的配置,我们可以通过键入退出我们的虚拟环境:
1deactivate
提示中的虚拟环境指示器将被删除。
创建一个 Gunicorn systemd 服务文件
我们已经测试了Gunicorn可以与我们的Django应用程序进行交互,但我们应该实施一个更强大的启动和停止应用程序服务器的方式。
创建并在文本编辑器中使用sudo
特权打开 Gunicorn 的 systemd 服务文件:
1sudo nano /etc/systemd/system/gunicorn.service
我们将在这里列出我们的服务的描述,并告诉 init 系统在实现网络目标后才启动此操作:
1[label /etc/systemd/system/gunicorn.service]
2[Unit]
3Description=gunicorn daemon
4After=network.target
接下来,我们将打开[服务]
部分,我们将指定我们想要处理的用户和组,我们将给我们的常规用户帐户拥有这个过程,因为它拥有所有相关的文件。
然后我们将绘制工作目录并指定要使用的命令来启动服务. 在这种情况下,我们将不得不指定在我们的虚拟环境中安装的Gunicorn可执行的完整路径。我们将它绑定到项目目录中的Unix插槽,因为Nginx安装在同一台计算机上。这比使用网络端口更安全,更快。我们也可以在这里指定任何可选的Gunicorn调整。
1[label /etc/systemd/system/gunicorn.service]
2[Unit]
3Description=gunicorn daemon
4After=network.target
5
6[Service]
7User=sammy
8Group=www-data
9WorkingDirectory=/home/sammy/myproject
10ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
最后,我们将添加一个[安装]
部分,这将告诉系统d如果我们允许该服务在启动时启动,该服务将连接到什么。
1[label /etc/systemd/system/gunicorn.service]
2[Unit]
3Description=gunicorn daemon
4After=network.target
5
6[Service]
7User=sammy
8Group=www-data
9WorkingDirectory=/home/sammy/myproject
10ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
11
12[Install]
13WantedBy=multi-user.target
这样,我们的 systemd 服务文件就完成了. 现在保存并关闭它。
我们现在可以启动我们创建的Gunicorn服务,并启用它,以便它在启动时开始:
1sudo systemctl start gunicorn
2sudo systemctl enable gunicorn
我们可以通过检查插件文件来确认操作成功。
查找 Gunicorn Socket 文件
检查过程的状态,看看它是否能够开始:
1sudo systemctl status gunicorn
接下来,检查项目目录中是否存在myproject.sock
文件:
1ls /home/sammy/myproject
1[secondary_label Output]
2manage.py myproject myprojectenv myproject.sock static
如果systemctl status
命令显示出现错误,或者您在目录中找不到myproject.sock
文件,则表示Gunicorn无法正确启动。
1sudo journalctl -u gunicorn
请查看日志中的消息,了解 Gunicorn 遇到问题的地方. 您可能遇到问题的原因有很多,但如果 Gunicorn 无法创建插件文件,这是由于以下原因之一:
- 项目文件由
root
用户拥有,而不是sudo
用户 - 在
ExecStart
指令中WorkingDirectory
路径不在/etc/systemd/system/gunicorn.service
文件中指向项目目录 - 在
ExecStart
指令中gunicorn
过程所提供的配置选项不正确。 检查以下项目:
- 在虚拟环境中
gunicorn
二进制路径指向虚拟环境中的二进制的实际位置 - 在
Working Directory
指令中定义了要在gunicorn
指令中创建一个文件, Gunicorn 可以访问 - `my project.wsgi:application
如果您对 /etc/systemd/system/gunicorn.service
文件进行更改,请重新加载 DAEMON 来重新读取服务定义,然后通过键入:
1sudo systemctl daemon-reload
2sudo systemctl restart gunicorn
确保您在继续之前解决上述任何问题。
配置 Nginx 到 Proxy Pass 到 Gunicorn
现在Gunicorn已设置,我们需要配置 Nginx 来将流量传输到进程中。
首先,在 Nginx 的可用站点
目录中创建并打开一个新的服务器块:
1sudo nano /etc/nginx/sites-available/myproject
在内部,打开一个新的服务器块,我们将首先指定该块应该在正常端口80上听,并应响应我们的服务器的域名或IP地址:
1[label /etc/nginx/sites-available/myproject]
2server {
3 listen 80;
4 server_name server_domain_or_IP;
5}
接下来,我们会告诉 Nginx 忽略找到 favicon 的任何问题,我们还会告诉它在我们的 `~/myproject/static’ 目录中收集的静态资产在哪里找到。
1[label /etc/nginx/sites-available/myproject]
2server {
3 listen 80;
4 server_name server_domain_or_IP;
5
6 location = /favicon.ico { access_log off; log_not_found off; }
7 location /static/ {
8 root /home/sammy/myproject;
9 }
10}
最后,我们将创建一个位置 / {}
块,以匹配所有其他请求. 在这个位置中,我们将包括标准的proxy_params
文件,包括在 Nginx 安装中,然后我们将流量传输到我们的 Gunicorn 过程创建的接口:
1[label /etc/nginx/sites-available/myproject]
2server {
3 listen 80;
4 server_name server_domain_or_IP;
5
6 location = /favicon.ico { access_log off; log_not_found off; }
7 location /static/ {
8 root /home/sammy/myproject;
9 }
10
11 location / {
12 include proxy_params;
13 proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
14 }
15}
保存并关闭文件完成后. 现在,我们可以通过链接到网站启用
目录来启用该文件:
1sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
通过键入测试您的 Nginx 配置以检测语法错误:
1sudo nginx -t
如果没有报告错误,请继续通过键入重新启动 Nginx:
1sudo systemctl restart nginx
最后,我们需要打开我们的防火墙,以便在端口上正常流量 80. 由于我们不再需要访问开发服务器,我们也可以删除打开端口 8000 的规则:
1sudo ufw delete allow 8000
2sudo ufw allow 'Nginx Full'
您现在应该能够访问您的服务器的域或IP地址来查看您的应用程序。
<$>[注] [标签注] 配置 Nginx 后,下一步应该是使用 SSL/TLS 来确保服务器的流量。
如果您有域名,获取 SSL 证书以保护您的流量最简单的方法是使用 Let's Encrypt. 遵循 此指南在 Ubuntu 16.04 上设置 Let's Encrypt with Nginx。
如果您没有域名,您仍然可以使用自签名的SSL证书(https://andsky.com/tech/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-in-ubuntu-16-04)来保护您的网站进行测试和学习。
解决问题 Nginx 和 Gunicorn
如果此最后一步未显示您的应用程序,则需要解决安装问题。
Nginx将显示默认页面而不是Django应用程序
如果 Nginx 显示默认页面而不是向您的应用程序代理,这通常意味着您需要在 /etc/nginx/sites-available/myproject’ 文件中调整
server_name` 以指向您的服务器的 IP 地址或域名。
Nginx 使用server_name
来确定使用哪个服务器块来响应请求. 如果您看到默认的 Nginx 页面,这是一个迹象,表明 Nginx 无法明确匹配请求到一个 sever 块,因此它会返回在/etc/nginx/sites-available/default
中定义的默认块。
项目服务器块中的server_name
必须比要选择的默认服务器块中的server_name
更为具体。
Nginx 顯示 502 Bad Gateway 錯誤,而不是 Django 應用程式
502 错误表明 Nginx 无法成功代理请求. 各种配置问题以 502 错误表达,因此需要更多信息才能正确解决问题。
寻找更多信息的主要场所是在 Nginx 的错误日志中。 一般来说,这会告诉您在代理事件期间引起的问题的条件。
1sudo tail -F /var/log/nginx/error.log
现在,请在浏览器中提出另一个请求,以生成新错误(尝试刷新页面)。
你可能会看到以下的一些信息:
connect() 到 unix:/home/sammy/myproject/myproject.sock 失败了(2:没有此类文件或目录)
這表明 Nginx 無法在指定位置找到「myproject.sock」檔案,您應該將在「/etc/nginx/sites-available/myproject」檔案中定義的「proxy_pass」位置與您項目目錄中生成的「myproject.sock」檔案的實際位置進行比較。
如果您无法在项目目录中找到myproject.sock
文件,这通常意味着gunicorn
过程无法创建它。
connect() 到 unix:/home/sammy/myproject/myproject.sock 失败了(13:允许被拒绝)
这表明 Nginx 由于权限问题无法连接到 Gunicorn 接口. 通常情况下,这种情况发生在使用 root 用户而不是 sudo
用户时。
如果在 root 目录 (/
) 和 myproject.sock 文件之间有有限的权限,则会发生这种情况,我们可以通过将我们的 socket 文件的绝对路径传递到 'namei' 命令来查看 socket 文件及其每个母目录的权限和所有权值:
1namei -nom /home/sammy/myproject/myproject.sock
1[secondary_label Output]
2f: /home/sammy/myproject/myproject.sock
3 drwxr-xr-x root root /
4 drwxr-xr-x root root home
5 drwxr-xr-x sammy sammy sammy
6 drwxrwxr-x sammy sammy myproject
7 srwxrwxrwx sammy www-data myproject.sock
输出显示了每个目录组件的权限. 通过查看权限(第一列),所有者(第二列)和组所有者(第三列),我们可以确定接口文件的访问类型是允许的。
在上面的示例中,接口文件和导致接口文件的每个目录都有世界读取和执行权限(目录的权限列以r-x
而不是---
结束)。
如果连接到连接器的任何目录都没有世界读取和执行权限,那么 Nginx 将无法访问连接器,而不允许世界读取和执行权限,或者确保组所有权被赋予 Nginx 是组的一部分。
Django表示:无法连接到服务器:连接被拒绝
您在尝试访问 Web 浏览器中的应用程序部分时可能会看到 Django 的一个信息是:
1OperationalError at /admin/login/
2could not connect to server: Connection refused
3 Is the server running on host "localhost" (127.0.0.1) and accepting
4 TCP/IP connections on port 5432?
这表明 Django 无法连接到 Postgres 数据库,请通过键入确保 Postgres 实例正在运行:
1sudo systemctl status postgresql
如果不是,你可以启动它,并允许它在启动时自动启动(如果它尚未配置以这样做),键入:
1sudo systemctl start postgresql
2sudo 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 流程以通过键入获取更改:
1sudo systemctl restart gunicorn
如果您更改了gunicorn
systemd 服务文件,请重新加载 DAEMON 并通过键入重新启动过程:
1sudo systemctl daemon-reload
2sudo systemctl restart gunicorn
如果您更改了 Nginx 服务器块配置,请测试配置,然后通过键入 Nginx:
1sudo nginx -t && sudo systemctl restart nginx
这些命令有助于在调整配置时获取更改。
结论
在本指南中,我们已经在自己的虚拟环境中设置了一个Django项目,我们已经配置了Gunicorn来翻译客户端请求,以便Django能够处理这些请求。
Django 通过提供许多常见元素来简化项目和应用程序的创建,使您能够专注于独特的元素,通过利用本文中描述的通用工具链,您可以轻松地从单一服务器中服务您创建的应用程序。