如何在Debian 8安装配置Django与Postgres,Nginx和Gunicorn

Django是一个强大的网络框架,可以帮助你让你的Python应用程序或网站离地面。 Django包括一个简化的开发服务器,用于在本地测试代码,但对于任何与生产相关的任何事情,一个更安全和强大的Web服务器...

介绍

Django是一个强大的网络框架,可以帮助你让你的Python应用程序或网站离地面。 Django包括一个用于在本地测试代码的简化开发服务器,但是对于与生产有关的任何事情,需要一个更安全和更强大的Web服务器。 在本指南中,我们将演示如何在Debian 8上安装和配置一些组件,以支持和提供Django应用程序。我们将设置一个PostgreSQL数据库,而不是使用默认的SQLite数据库。我们将配置Gunicorn应用程序服务器与我们的应用程序接口。然后我们将设置Nginx反向代理Gunicorn,让我们访问其安全和性能功能来服务我们的应用程序。

先决条件和目标

为了完成这个指南,你应该有一个非root用户耳目一新的Debian 8服务器实例sudo配置权限。 你可以学习如何通过我们的运行设置此服务器初始设置指南 。 我们将在虚拟环境中安装Django。将Django安装到特定于您的项目的环境中将允许单独处理您的项目及其需求。 一旦我们的数据库和应用程序启动并运行,我们将安装和配置Gunicorn应用程序服务器。这将作为我们的应用程序的接口,将HTTP中的客户端请求转换为我们的应用程序可以处理的Python调用。然后我们将在Gunicorn之前设置Nginx,以利用其高性能连接处理机制和易于实现的安全特性。 让我们开始吧。

从Debian存储库安装软件包

要开始该过程,我们将从Debian存储库下载并安装我们需要的所有项目。我们将使用Python包管理器pip稍后安装附加组件。 我们需要更新本地apt包索引,然后下载并安装软件包。我们安装的包取决于您的项目将使用的Python版本。 如果您正在使用Python 2,请键入:
sudo apt-get update
sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx
如果您正在使用Python 3,键入:
sudo apt-get update
sudo 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的管理用户。 我们需要使用此用户来执行管理任务。 我们可以使用sudo,并在用户名通过与-u选项。 键入以下内容登录到交互式Postgres会话:
sudo -u postgres psql
你会得到一个PostgreSQL提示符,我们可以设置我们的要求。 首先,为您的项目创建一个数据库:
注意
每个Postgres语句必须以分号结束,因此请确保您的命令以一个结束,以避免问题。
CREATE DATABASE myproject;
CREATE DATABASE
接下来,为我们的项目创建一个数据库用户。请务必选择安全的密码:
CREATE USER myprojectuser WITH PASSWORD 'password';
CREATE ROLE
接下来,我们将修改刚刚创建的用户的几个连接参数。这将加速数据库操作,以便在每次建立连接时不必查询和设置正确的值。 我们将默认编码设置为UTF-8,Django期望。我们还将默认事务隔离方案设置为“读提交”,这会阻止从未提交的事务读取。最后,我们设置时区。缺省情况下,我们的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';
ALTER ROLE
ALTER ROLE
ALTER ROLE
现在,我们可以让我们的新用户访问以管理我们的新数据库:
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
GRANT
完成后,通过键入以下命令退出PostgreSQL提示符:
\q
你应该返回你的shell会话。

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

现在我们有了我们的数据库,我们可以开始获得其余的项目需求了。我们将在虚拟环境中安装我们的Python需求,以便于管理。 要做到这一点,我们首先需要访问virtualenv命令。 我们可以安装这个pip 。 如果您正在使用Python 2,请键入:
sudo pip install virtualenv
如果您正在使用Python 3,键入:
sudo pip3 install virtualenv
随着virtualenv安装后,我们就可以开始形成我们的项目。创建并移动到一个目录,我们可以保留我们的项目文件:
mkdir ~/myproject
cd ~/myproject
在项目目录中,通过键入以下内容创建Python虚拟环境:
virtualenv venv
这将创建一个名为venv你中myproject目录。 在内部,它会安装Python和本地版本的本地版本pip 。我们可以使用它为我们的项目安装和配置一个孤立的Python环境。 在我们安装我们项目的Python需求之前,我们需要激活虚拟环境。你可以通过键入:
source venv/bin/activate
您的提示应该更改为表示您现在在Python虚拟环境中操作。它看起来是这样的: ( venv ) user @ host :~/ myproject $ 。 随着虚拟环境活跃,安装Django,Gunicorn和psycopg2与本地实例PostgreSQL的适配器pip
注意
无论哪个版本的Python您正在使用,当虚拟环境中被激活,你应该使用pip命令(不pip3 )。
pip install django gunicorn psycopg2
这些组件将安装在我们的虚拟环境中,与我们的全局软件包隔离。

创建和配置新的Django项目

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

创建Django项目

由于我们已经有一个项目目录,我们将告诉Django在这里安装文件。现在,我们可以开始我们的内Django项目myproject目录。这将创建一个具有相同名称的子目录来保存代码本身,并将在当前目录中创建一个管理脚本: 注意:确保在使这一设置正确命令的末尾添加点。因为我们已经创建了一个父项目目录来保存我们的虚拟环境目录,所以我们不想要创建额外的目录级别,如果我们离开点。
django-admin.py startproject myproject .
您当前的目录结构应如下所示:
.
└── ./myproject/
    ├── manage.py
    ├── myproject/
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── venv/
        └── . . .
正如你所看到的,我们有一个持有父项目目录manage.py脚本,一个内部项目目录,并venv我们前面创建的虚拟环境目录。

调整项目设置

我们应该对我们新创建的项目文件做的第一件事是调整设置。在文本编辑器中打开设置文件:
nano ~/myproject/myproject/settings.py
通过查找开始ALLOWED_HOSTS指令。 这定义了可用于连接到Django实例的地址或域名的白名单。 任何传入的请求与主机头不在此名单将引发异常。 Django要求您设置此项以防止某类安全漏洞。 在方括号中,列出与您的Django服务器相关联的IP地址或域名。每个项目用逗号分隔的条目报价上市。如果您希望响应域和任何子域的请求,请在该条目的开头添加一个句点。在下面的代码段中,有几个注释掉的示例用于演示格式条目的正确方式:
〜/ myproject / myproject / settings.py
. . .
# 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', . . .]
接下来,找到配置数据库访问的部分。它将与开始DATABASES 。文件中的配置用于SQLite数据库。我们已经为我们的项目创建了一个PostgreSQL数据库,所以我们需要调整设置。 使用PostgreSQL数据库信息更改设置。我们告诉Django使用psycopg2 ,我们在安装适配器pip 。 我们需要给出数据库名称,数据库用户名,数据库用户的密码,然后指定数据库位于本地计算机上。 您可以将PORT设置为空字符串:
〜/ myproject / myproject / settings.py
. . .

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

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

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
保存并在完成后关闭文件。

完成初始项目设置

现在,我们可以使用管理脚本将初始数据库模式迁移到PostgreSQL数据库:
cd ~/myproject
./manage.py makemigrations
./manage.py migrate
通过键入以下内容为项目创建管理用户:
./manage.py createsuperuser
您必须选择用户名,提供电子邮件地址,然后选择并确认密码。 我们可以通过键入以下内容将所有静态内容收集到我们配置的目录位置:
./manage.py collectstatic
您必须确认操作。然后,静态文件将被放置在一个名为static项目目录之内。 注:在尝试开发服务器,确保在防火墙上打开的端口。 如果你碰巧运行ufw防火墙,您可以打开通过键入相应的端口:
sudo ufw allow 8000
如果你正在运行iptables防火墙,你需要确切的命令取决于您当前的防火墙配置。 对于大多数配置 ,这个命令应该工作:
sudo iptables -I INPUT -p tcp --dport 8000 -j ACCEPT
最后,您可以使用此命令启动Django开发服务器来测试您的项目:
./manage.py runserver 0.0.0.0:8000
在Web浏览器,访问你的服务器的域名或IP地址后面:8000
http://server_domain_or_IP:8000
您应该会看到默认的Django索引页面: Django索引页 如果您添加/admin在地址栏中的URL的最后,你会被提示输入您已创建的管理员用户名和密码createsuperuser命令: Django管理员登录 验证后,您可以访问默认的Django管理界面: Django管理界面 当您完成浏览时,在终端窗口中按CTRL-C关闭开发服务器。

测试Gunicorn的能力服务项目

在离开我们的虚拟环境之前,我们要做的最后一件事是测试Gunicorn,以确保它可以为应用程序提供服务。我们可以轻松地通过键入:
cd ~/myproject
gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application
这将在Django开发服务器运行的同一个接口上启动Gunicorn。您可以返回并再次测试该应用。 注:管理界面不会有任何因为Gunicorn应用的造型不知道负责这一静态CSS内容。 我们通过指定Django的相对目录路径通过Gunicorn模块wsgi.py文件,该文件的入口点到我们的应用程序,使用Python的模块语法。 在这个文件中,一被调用的功能application被定义,其用于与应用程序进行通信。 要了解更多关于WSGI规范,请点击这里 。 完成测试后,在终端窗口中按CTRL-C停止Gunicorn。 我们现在已经完成了配置我们的Django应用程序。我们可以通过键入以下内容退出我们的虚拟环境:
deactivate
应该从shell提示符中删除虚拟环境前缀,表明您不再位于虚拟环境中。

创建一个Gunicorn systemd服务文件

我们测试了Gunicorn可以与我们的Django应用程序交互,但我们应该实现一个更可靠的方式启动和停止应用程序服务器。为了实现这一点,我们将创建一个systemd服务文件。 创建并打开一个systemd服务文件Gunicorn与sudo在文本编辑器的权限:
sudo nano /etc/systemd/system/gunicorn.service
开始与[Unit]部分,它是用来指定元数据和依赖关系。我们将在这里描述我们的服务,并告诉init系统只有在达到网络目标后才启动:
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target
接下来,我们将打开[Service]部分。 我们将指定要在其下运行的用户和组。 我们将给予流程的常规用户帐户所有权,因为它拥有所有相关文件。 我们将给组所有权的www-data组,以便Nginx的可以Gunicorn很容易沟通。 然后,我们将映射工作目录并指定用于启动服务的命令。在这种情况下,我们必须指定Gunicorn可执行文件的完整路径,该路径安装在我们的虚拟环境中。因为安装在同一台计算机上的Nginx我们将其绑定到一个Unix套接字项目目录之内。这比使用网络端口更安全和更快。我们还可以在这里指定任何可选的Gunicorn调整。例如,在这种情况下,我们指定了3个工作进程:
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
ExecStart=/home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
最后,我们将添加一个[Install]部分。这将告诉systemd什么链接这个服务,如果我们启用它在启动时启动。我们希望此服务在常规多用户系统启动并运行时启动:
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
ExecStart=/home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application

[Install]
WantedBy=multi-user.target
这样,我们的systemd服务文件就完成了。保存并立即关闭。 我们现在可以启动我们创建的Gunicorn服务,并启用它,以便它在启动时启动:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
Created symlink from /etc/systemd/system/multi-user.target.wants/gunicorn.service to /etc/systemd/system/gunicorn.service.
键入以下内容检查服务的状态:
sudo systemctl status gunicorn
● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled)
   Active: active (running) since Wed 2016-12-21 21:05:07 UTC; 49s ago
 Main PID: 10154 (gunicorn)
   CGroup: /system.slice/gunicorn.service
           ├─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
           ├─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
           ├─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
           └─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

Dec 21 21:05:07 debian-512mb-nyc3-01 systemd[1]: Started gunicorn daemon.
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Starting gunicorn 19.6.0
Dec 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)
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Using worker: sync
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10157] [INFO] Booting worker with pid: 10157
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10158] [INFO] Booting worker with pid: 10158
Dec 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套接字文件:
ls -l ~/myproject
total 16
-rwxr-xr-x 1 sammy sammy     807 Dec 21 20:46 manage.py
drwxr-xr-x 3 sammy sammy    4096 Dec 21 20:54 myproject
srwxrwxrwx 1 sammy www-data    0 Dec 21 21:05 myproject.sock
drwxr-xr-x 3 sammy sammy    4096 Dec 21 20:54 static
drwxr-xr-x 5 sammy sammy    4096 Dec 21 20:41 venv
正如你所看到的,socket是否有和www-data组拥有组所有权。

配置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;
}
接下来,如果找不到favicon,我们可以告诉Nginx忽略错误。我们也将告诉它在哪里可以找到,我们收集在我们的静态资产~/ myproject /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/myproject;
    }
}
最后,我们将创建一个location / {}块匹配所有其他请求。 这里面的位置,我们将包括标准proxy_params包含在Nginx的安装文件,然后我们会通过将流量发送到我们的Gunicorn过程中创建的socket:
/ 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/myproject;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
    }
}
保存并在完成后关闭文件。现在,我们可以通过它链接到启用文件sites-enabled目录:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
键入以下内容来测试Nginx配置的语法错误:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
如果没有报告错误,请继续并通过键入以下命令重新启动Nginx:
sudo systemctl restart nginx
注意:如果你启用了防火墙,调整再次删除端口8000,并允许80端口正常访问。 如果你碰巧运行ufw防火墙,您可以打开通过键入相应的端口:
sudo ufw delete allow 8000
sudo ufw allow 'WWW'
如果你正在运行iptables防火墙,你需要确切的命令取决于您当前的防火墙配置。 对于大多数配置 ,这些命令应该工作:
sudo iptables -D INPUT -p tcp --dport 8000 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
您现在应该可以转到您的服务器的域或IP地址以查看您的应用程序,而无需指定端口。
注意
配置Nginx后,下一步应该是使用SSL / TLS确保流量到服务器。这很重要,因为没有它,所有信息,包括密码都通过网络以纯文本发送。 如果您有域名,获取SSL证书以确保流量的最简单方法是使用Let's Encrypt。按照本指南设置让我们Nginx的加密Debian 8 。 如果你没有一个域名,你仍然可以保证站点的安全测试,并与学习的自签名的SSL证书

结论

在本指南中,我们在其自己的虚拟环境中设置了一个Django项目。我们已经配置了Gunicorn来翻译客户端请求,以便Django可以处理它们。之后,我们设置Nginx作为反向代理来处理客户端连接,并根据客户端请求提供正确的项目。 Django通过提供许多常用的部分来简化创建项目和应用程序,使您能够专注于独特的元素。通过利用本文中描述的通用工具链,您可以轻松地从单个服务器提供您创建的应用程序。