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

介绍

Django 是一个强大的 Web 框架,可以帮助您将您的 Python 应用程序或网站从地面上获得。Django 包含一个简化开发服务器来本地测试您的代码,但对于任何与生产有关的内容,需要一个更安全、更强大的 Web 服务器。

在本指南中,我们将展示如何在 Debian 8 上安装和配置某些组件以支持和服务 Django 应用程序. 我们将设置一个 PostgreSQL 数据库,而不是使用默认 SQLite 数据库. 我们将配置 Gunicorn 应用程序服务器与我们的应用程序进行交互。

前提和目标

要完成本指南,你应该有一个新的 Debian 8 服务器实例,有一个非根用户,配置了sudo特权,你可以通过我们的 初始服务器设置指南来学习如何设置此设置。

将 Django 安装在虚拟环境中,而将 Django 安装在您项目的特定环境中,将使您的项目及其需求能够单独处理。

一旦我们的数据库和应用程序启动并运行,我们将安装和配置Gunicorn应用程序服务器,这将作为我们的应用程序的界面,将客户端请求翻译成HTTP到我们的应用程序可以处理的Python呼叫。

让我们开始吧。

从 Debian 存储库中安装包

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

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

如果您正在使用 Python 2,请键入:

1sudo apt-get update
2sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx

如果您正在使用 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提示,我们可以设置我们的要求。

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

<$>[注] [标签注] 每个 Postgres 语句必须以半列结束,因此请确保您的命令以一个结束以避免问题。

1CREATE DATABASE myproject;
1[secondary_label Output]
2CREATE DATABASE

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

1CREATE USER myprojectuser WITH PASSWORD 'password';
1[secondary_label Output]
2CREATE ROLE

接下来,我们将更改我们刚刚创建的用户的一些连接参数,这将加快数据库操作,以便每次建立连接时不需要查询和设置正确的值。

我们正在将默认编码设置为 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';
1[secondary_label Output]
2ALTER ROLE
3ALTER ROLE
4ALTER ROLE

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

1GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
1[secondary_label Output]
2GRANT

完成后,通过键入退出 PostgreSQL 提示:

1\q

你应该被带回你的壳会话。

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

现在我们有我们的数据库,我们可以开始准备剩余的项目要求,我们将在虚拟环境中安装我们的Python要求,以便更容易管理。

要做到这一点,我们首先需要访问virtualenv命令,我们可以使用pip来安装它。

如果您正在使用 Python 2,请键入:

1sudo pip install virtualenv

如果您正在使用 Python 3,请键入:

1sudo pip3 install virtualenv

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

1mkdir ~/myproject
2cd ~/myproject

在项目目录中,通过键入创建一个Python虚拟环境:

1virtualenv venv

这将创建一个名为venv的目录在你的myproject目录中。内部,它将安装一个本地版本的Python和一个本地版本的pip

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

1source venv/bin/activate

您的提示应更改,以表示您现在在Python虚拟环境中运行,它将看起来像这样: (venv)user@host:~/myproject$

随着虚拟环境的启动,安装 Django、Gunicorn 和psycopg2 PostgreSQL 适配器,使用本地实例pip:

<$>[注] [标签注] 无论您使用的是哪个版本的Python,在激活虚拟环境时,您应该使用pip命令(而不是pip3)。

1pip install django gunicorn psycopg2

这些组件将安装在我们的虚拟环境中,与我们的全球包隔绝。

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

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

创建 Django 项目

由于我们已经有一个项目目录,我们会告诉Django在这里安装文件,现在我们可以在我们的myproject目录中启动一个Django项目,这将创建一个同名子目录,以保持代码本身,并在当前目录中创建一个管理脚本:

<$>[注] 注: 请确保在命令的末尾添加点,以便此设置正确。由于我们已经创建了一个主项目目录以保留我们的虚拟环境目录,我们不希望如果我们离开点,将创建的额外目录级别。

1django-admin.py startproject myproject .

您的当前目录结构应该是这样的:

 1.
 2└── ./myproject/
 3    ├── manage.py
 4    ├── myproject/
 5    │   ├── __init__.py
 6    │   ├── settings.py
 7    │   ├── urls.py
 8    │   └── wsgi.py
 9    └── venv/
10        └── . . .

正如你所看到的,我们有一个主项目目录,其中包含一个manage.py脚本,一个内部项目目录和我们之前创建的venv虚拟环境目录。

调整项目设置

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

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数据库:

1cd ~/myproject
2./manage.py makemigrations
3./manage.py migrate

创建一个项目的管理用户,键入:

1./manage.py createsuperuser

您将需要选择用户名,提供电子邮件地址,并选择并确认密码。

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

1./manage.py collectstatic

然后,静态文件将被放置在项目目录中的名为静态的目录中。

<$>[注] 注: 在尝试开发服务器之前,请确保在防火墙中打开端口。

如果你正在运行一个ufw防火墙,你可以通过键入打开相应的端口:

1sudo ufw allow 8000

如果您正在运行iptables防火墙,您需要的确切命令取决于当前的防火墙配置。

1sudo iptables -I INPUT -p tcp --dport 8000 -j ACCEPT

美元

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

1./manage.py runserver 0.0.0.0:8000

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

1http://server_domain_or_IP:8000

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

Django index page

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

Django admin login

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

Django admin interface

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

测试 Gunicorn 服务项目的能力

在离开我们的虚拟环境之前,我们要做的最后一件事是测试Gunicorn,以确保它可以服务于应用程序。

1cd ~/myproject
2gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application

这将启动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/venv/bin/gunicorn --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/venv/bin/gunicorn --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
1[secondary_label Output]
2Created symlink from /etc/systemd/system/multi-user.target.wants/gunicorn.service to /etc/systemd/system/gunicorn.service.

通过键入检查服务的状态:

1sudo systemctl status gunicorn
 1[secondary_label Output]
 2 gunicorn.service - gunicorn daemon
 3   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled)
 4   Active: active (running) since Wed 2016-12-21 21:05:07 UTC; 49s ago
 5 Main PID: 10154 (gunicorn)
 6   CGroup: /system.slice/gunicorn.service
 7           ├─10154 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
 8           ├─10157 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
 9           ├─10158 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
10           └─10159 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
11
12Dec 21 21:05:07 debian-512mb-nyc3-01 systemd[1]: Started gunicorn daemon.
13Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Starting gunicorn 19.6.0
14Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Listening at: unix:/home/sammy/myproject/myproject.sock (10154)
15Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Using worker: sync
16Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10157] [INFO] Booting worker with pid: 10157
17Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10158] [INFO] Booting worker with pid: 10158
18Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10159] [INFO] Booting worker with pid: 10159

最重要的事情是,单位是活跃的。

如果你列出你的 `~/myproject' 目录的内容,你应该看到 Unix 接口文件:

1ls -l ~/myproject
1[secondary_label Output]
2total 16
3-rwxr-xr-x 1 sammy sammy 807 Dec 21 20:46 manage.py
4drwxr-xr-x 3 sammy sammy 4096 Dec 21 20:54 myproject
5srwxrwxrwx 1 sammy www-data 0 Dec 21 21:05 myproject.sock
6drwxr-xr-x 3 sammy sammy 4096 Dec 21 20:54 static
7drwxr-xr-x 5 sammy sammy 4096 Dec 21 20:41 venv

正如你所看到的,插槽就在那里,而www-data组拥有组所有权。

配置 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
1[secondary_label Output]
2nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
3nginx: configuration file /etc/nginx/nginx.conf test is successful

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

1sudo systemctl restart nginx

<$>[注] 注: 如果启用了防火墙,请将其调整为再次移除端口 8000,并允许正常访问端口 80。

如果你正在运行一个ufw防火墙,你可以通过键入打开相应的端口:

1sudo ufw delete allow 8000
2sudo ufw allow 'WWW'

如果您正在运行iptables防火墙,您需要的确切命令取决于当前的防火墙配置。

1sudo iptables -D INPUT -p tcp --dport 8000 -j ACCEPT
2sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT

美元

您现在应该能够访问您的服务器的域或 IP 地址以查看您的应用程序,而无需指定端口。

<$>[注] [标签注] 配置 Nginx 后,下一步应该是通过 SSL/TLS 确保服务器的流量,因为没有它,所有信息,包括密码,都通过网络以简单的文本发送。

如果您有域名,获取 SSL 证书以保护您的流量最简单的方法是使用 Let's Encrypt. 遵循本指南到 Debian 8 上设置 Let's Encrypt with Nginx

如果您没有域名,您仍然可以使用自签名的SSL证书(https://andsky.com/tech/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-on-debian-8)来保护您的网站进行测试和学习。

结论

在本指南中,我们已经在自己的虚拟环境中设置了一个Django项目,我们已经配置了Gunicorn来翻译客户端请求,以便Django能够处理这些请求。

Django 通过提供许多常见元素来简化项目和应用程序的创建,使您能够专注于独特的元素,通过利用本文中描述的通用工具链,您可以轻松地从单一服务器中服务您创建的应用程序。

Published At
Categories with 技术
comments powered by Disqus