如何利用DigitalOcean托管数据库和空间建立可扩展的Django应用程序

介绍

Django是一个强大的网页框架,可以帮助您快速实现您的Python应用程序或网站,它包括一些方便的功能,如(https://en.wikipedia.org/wiki/Object-relational_mapping),Python API,以及应用程序的可自定义管理界面。它还包括(https://docs.djangoproject.com/en/2.1/topics/cache/)缓存框架,并通过其(URL Dispatcher)和(https://docs.djangoproject.com/en/2.1/topics/http/urls/)模板系统(https://docs.djangoproject.com/en/2.1/topics/templates/)鼓励清洁的应用设计。

除了盒子之外,Django还包括了一台用于测试和本地开发的最小的Web服务器,但它应该配备一个更强大的服务基础设施,用于生产使用案例。

在本指南中,我们将通过将静态文件(如JavaScript和CSS风格表)卸载到DigitalOcean Spaces,并可选地使用一个 Content Delivery Nnetwork,或CDN,将这些文件存储在更接近终端用户的位置,以减少传输时间,并使用DigitalOcean Managed PostgreSQL database作为我们的数据存储,以简化数据层,并避免需要手动配置可扩展的PostgreSQL数据库。

前提条件

在您开始使用本指南之前,您应该拥有以下内容:

  • 一个新的 Ubuntu 18.04 服务器实例,具有基本防火墙和配置sudo特权的非根用户。您可以通过运行 Initial Server Setup with Ubuntu 18.04来学习如何设置此设置。
  • A DigitalOcean Managed PostgreSQL Cluster. 要了解如何创建一个群集,请参阅 DigitalOcean [Managed Databases] 产品文档(https://www.digitalocean.com/docs/databases/how-to/clusters/create/)。
  • A DigitalOcean Space to store your Django project’s static files and set of Access Keys for this Space. 要学习如何创建一个空间,请参阅 How to Create Spaces 产品文档,并学习如何创建空间的访问密钥,请参阅 [Share to Spaces with Access

步骤 1 — 从 Ubuntu 存储库中安装包

首先,我们将从Ubuntu存储库下载并安装我们需要的所有项目,我们将使用Python包管理器pip稍后安装额外的组件。

我们需要先更新本地apt包索引,然后下载和安装包。

在本指南中,我们将使用 Django 与 Python 3. 要安装所需的库,请登录您的服务器并键入:

1sudo apt update
2sudo apt install python3-pip python3-dev libpq-dev curl postgresql-client

这将安装pip,构建 Gunicorn 所需的 Python 开发文件,构建 Pyscopg PostgreSQL Python 适配器所需的 libpq 标题文件,以及 PostgreSQL 命令行客户端。

当被提示开始下载和安装软件包时,点击Y,然后点击ENTER

接下来,我们将配置数据库以与我们的Django应用程序一起工作。

步骤 2 – 创建 PostgreSQL 数据库和用户

我们现在将为我们的Django应用程序创建一个数据库和数据库用户。

首先,请从 Cloud 控制面板导航到 DataBases,然后点击您的数据库,您应该看到一个 连接细节框,其中包含您的群集的一些参数。

回到命令行上,使用这些凭据和我们刚刚安装的psql PostgreSQL 客户端登录您的集群:

1psql -U username -h host -p port -d database -set=sslmode=require

当被提示时,输入显示在Postgres用户名旁边的密码,然后点击ENTER

您将收到一个PostgreSQL提示,您可以管理数据库。

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

1CREATE DATABASE polls;

<$>[注] 注: 每个 Postgres 语句都必须以半字符号结束,因此,如果您遇到问题,请确保您的命令以一个结束。

我们现在可以切换到调查数据库:

1\c polls;

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

1CREATE USER myprojectuser WITH PASSWORD 'password';

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

我们正在将默认的编码设置为UTF-8,这是Django的预期。我们还将默认的交易隔离方案设置为读取承诺,这是从未承诺的交易中读取的块。最后,我们正在设置时区。

在 PostgreSQL 提示中输入以下命令:

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 polls TO myprojectuser;

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

1\q

您的 Django 应用程序现在已经准备好连接和管理此数据库。

在下一步,我们将安装virtualenv,为我们的Django项目创建一个Python虚拟环境。

步骤 3:为您的项目创建一个Python虚拟环境

现在我们已经设置了我们的数据库以与我们的应用程序工作,我们将创建一个Python虚拟环境,将这个项目的依赖性与系统的全球Python安装隔离。

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

升级pip并通过键入安装包:

1sudo -H pip3 install --upgrade pip
2sudo -H pip3 install virtualenv

安装了virtualenv,我们可以创建一个目录来存储我们的Python虚拟环境,并与Django调查应用程序一起使用。

创建一个名为envs的目录,并导航:

1mkdir envs
2cd envs

在此目录中,创建一个名为调查的Python虚拟环境,键入:

1virtualenv polls

这将创建一个名为调查的目录,在envs目录中。内部,它将安装Python的本地版本和Pip的本地版本。

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

1source polls/bin/activate

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

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

<$>[注] 注: 当虚拟环境被激活时(当您的提示有(调查)之前),使用pip而不是pip3,即使您正在使用Python 3. 虚拟环境的副本的工具总是被命名为pip,无论Python版本。

1pip install django gunicorn psycopg2-binary

您现在应该拥有运行Django调查应用程序所需的所有软件,在下一步,我们将创建一个Django项目并安装该应用程序。

步骤 4 – 创建调查 Django 应用程序

我们现在可以设置我们的样本应用程序. 在本教程中,我们将使用从Django文档(https://docs.djangoproject.com/en/2.1/intro/tutorial01/)的民意调查演示应用程序。它由一个允许用户查看民意调查和投票的公共网站,以及一个管理控制面板,允许管理员修改,创建和删除民意调查。

在本指南中,我们将跳过教程步骤,并简单地从DigitalOcean社区克隆最终应用程序 django-polls repo

如果您想手动完成步骤,请在您的主目录中创建名为django-polls的目录,并导航:

1cd
2mkdir django-polls
3cd django-polls

从那里,你可以遵循官方 Django 文档中的 写你的第一个 Django 应用程序教程. 完成后,跳到 步骤 5)。

如果您只想克隆完成的应用程序,请导航到您的主目录并使用git来克隆 django-polls repo:

1cd
2git clone https://github.com/do-community/django-polls.git

「cd」插入它,并列出目录内容:

1cd django-polls
2ls

你应该看到以下对象:

1[secondary_label Output]
2LICENSE README.md manage.py mysite polls templates

「manage.py」是操纵应用程序的主要命令行实用程序。「polls」包含「polls」应用程序代码,而「mysite」包含项目范围代码和设置。

在运行应用程序之前,我们需要调整其默认设置并将其连接到我们的数据库。

步骤 5 – 调整应用设置

在此步骤中,我们将修改 Django 项目的默认配置以增加安全性,将 Django 连接到我们的数据库,并将静态文件收集到本地目录中。

首先,打开文本编辑器中的设置文件:

1nano ~/django-polls/mysite/settings.py

首先,找出「ALLOWED_HOSTS」指令,定义了您要使用的地址或域名列表,以便连接到 Django 实例。在本列表中不包含的 Host 标题的输入请求会引发一个例外。

在方块中,列出与您的 Django 服务器相关的 IP 地址或域名。 每个项目都应列入引文中,每个条目都分为一个字节。 您的列表还将包含本地主机,因为您将通过本地 Nginx 实例代理连接。 如果您希望包含整个域和任何子域的请求,请预先预定一个期限,直到输入开始。

在下面的片段中,有一些评论的例子,展示了这些条目应该是什么样子:

 1[label ~/django-polls/mysite/settings.py]
 2. . .
 3
 4# The simplest case: just add the domain name(s) and IP addresses of your Django server
 5# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
 6# To respond to 'example.com' and any subdomains, start the domain with a dot
 7# ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
 8ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
 9
10. . .

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

我们会告诉Django使用我们与pip安装的psycopg2数据库适配器,而不是默认的SQLite引擎。我们还会重复使用在 步骤 2中提到的 连接参数

更新数据库设置的文件:数据库名称(调查),数据库用户名,数据库用户密码,数据库主机端口

 1[label ~/django-polls/mysite/settings.py]
 2. . .
 3
 4DATABASES = {
 5    'default': {
 6        'ENGINE': 'django.db.backends.postgresql_psycopg2',
 7        'NAME': 'polls',
 8        'USER': 'myprojectuser',
 9        'PASSWORD': 'password',
10        'HOST': 'managed_db_host',
11        'PORT': 'managed_db_port',
12    }
13}
14
15. . .

接下来,移动到文件的底部,并添加一个设置,表示 static 文件应该放置在哪里。 这是必要的,以便 Nginx 能够处理这些项目的请求。

1[label ~/django-polls/mysite/settings.py]
2. . .
3
4STATIC_URL = '/static/'
5STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

保存并关闭文件,当你完成。

在此时,您已经配置了Django项目的数据库、安全和静态文件设置,如果您从一开始就遵循了调查教程,并且没有克隆GitHub复制程序,您可以转到 步骤 6

Django 设置文件包含一个SECRET_KEY变量,用于创建各种 Django 对象的哈希。重要的是,它被设置为一个独特的,不可预测的值。从 GitHub 存储库中清洗了SECRET_KEY变量,所以我们将使用一个名为get_random_secret_key()django Python 包内置的函数创建一个新的函数。

1python

您应该看到以下输出和速率:

1[secondary_label Output]
2Python 3.6.7 (default, Oct 22 2018, 11:32:17)
3[GCC 8.2.0] on linux
4Type "help", "copyright", "credits" or "license" for more information.
5>>>

从 Django 包中导入 get_random_secret_key 函数,然后拨打函数:

1from django.core.management.utils import get_random_secret_key
2get_random_secret_key()

将结果的密钥复制到您的剪辑板。

通过按CTRL+D来退出 Python 解释器。

接下来,在文本编辑器中再次打开设置文件:

1nano ~/django-polls/mysite/settings.py

查找SECRET_KEY变量并粘贴您刚刚生成的密钥:

1[label ~/django-polls/mysite/settings.py]
2. . .
3
4# SECURITY WARNING: keep the secret key used in production secret!
5SECRET_KEY = 'your_secret_key_here'
6
7. . .

保存并关闭文件。

现在我们将使用Django开发服务器在本地测试应用程序,以确保一切都被正确配置。

步骤6:测试应用程序

在运行Django开发服务器之前,我们需要使用manage.py工具来创建数据库架构并将静态文件收集到STATIC_ROOT目录中。

导航到项目的基本目录,并使用makemigrationsmigrate命令在我们的PostgreSQL数据库中创建初始数据库方案:

1cd django-polls
2./manage.py makemigrations
3./manage.py migrate

「makemigrations」将根据对Django模型所做的更改创建迁移,或基于数据库方案的更改。「migrate」将将这些迁移应用于数据库方案。

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

1./manage.py createsuperuser

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

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

1./manage.py collectstatic

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

如果您遵循最初的服务器设置指南,您应该有一个 UFW 防火墙来保护您的服务器. 为了测试开发服务器,我们必须允许访问我们将使用的端口。

创建一个8000端口的例外,键入:

1sudo ufw allow 8000

使用 Django 开发服务器测试应用程序

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

1./manage.py runserver 0.0.0.0:8000

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

1http://server_domain_or_IP:8000/polls

您应该看到 Polls app 界面:

Polls App Interface

要查看管理员界面,请访问您的服务器的域名或IP地址,然后是:8000和管理员界面的路径:

1http://server_domain_or_IP:8000/admin

您应该看到 Polls 应用程序管理员身份验证窗口:

Polls Admin Auth Page

输入您用createsuperuser命令创建的管理用户名和密码。

验证后,您可以访问 Polls 应用程序的管理界面:

Polls Admin Main Interface

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

使用 Gunicorn 测试应用程序

在卸载静态文件之前,我们要做的最后一件事是测试Gunicorn,以确保它能为应用程序提供服务,我们可以通过输入我们的项目目录并使用gunicorn来加载该项目的WSGI模块来做到:

1gunicorn --bind 0.0.0.0:8000 mysite.wsgi

这将启动Gunicorn在Django开发服务器正在运行的相同界面上,您可以返回并再次测试应用程序。

<$>[注] 注: 管理员界面将没有应用任何的样式,因为Gunicorn不知道如何找到负责此的静态CSS内容。

我们通过指定相对目录路径给Django的wsgi.py文件,这个文件定义了一个名为application的函数,该函数与应用程序通信。

当你完成测试时,在终端窗口中按CTRL-C来阻止Gunicorn。

现在我们将下载应用程序的静态文件到DigitalOcean Spaces。

步骤 7 – 将静态文件卸载到数字海洋空间

在这一点上,Gunicorn可以服务我们的Django应用程序,但不是它的静态文件. 通常我们会配置 Nginx来服务这些文件,但在本教程中,我们将将它们下载到DigitalOcean Spaces使用 django-storages插件. 这允许您通过集中其静态内容和释放服务器资源来轻松扩展Django。

有关将 Django 静态文件卸载到 Object 存储的完整指南,请参阅 How to Set Up Object Storage with Django

安装和配置django存储

django-storages包为Django提供S3Boto3Storage存储后端,它使用boto3库将文件上传到任何S3兼容的对象存储服务。

要開始,請使用「pip」安裝「django-storages」和「boto3」 Python 套件:

1pip install django-storages boto3

接下来,重新打开应用程序的 Django 设置文件:

1nano ~/django-polls/mysite/settings.py

导航到文件的INSTALLED_APPS部分,并将存储添加到安装的应用程序列表中:

 1[label ~/django-polls/mysite/settings.py]
 2. . .
 3
 4INSTALLED_APPS = [
 5    . . .
 6    'django.contrib.staticfiles',
 7    'storages',
 8]
 9
10. . .

再往下滚动到我们之前修改过的STATIC_URL。我们现在将重写这些值,并添加新的S3Boto3Storage后端参数。 删除您之前输入的代码,并添加以下块,其中包括您的空间的访问和位置信息。 请记住,请用您自己的信息来替换这里的突出值:

 1[label ~/django-polls/mysite/settings.py]
 2. . .
 3
 4# Static files (CSS, JavaScript, Images)
 5# https://docs.djangoproject.com/en/2.1/howto/static-files/
 6
 7AWS_ACCESS_KEY_ID = 'your_spaces_access_key'
 8AWS_SECRET_ACCESS_KEY = 'your_spaces_secret_key'
 9
10AWS_STORAGE_BUCKET_NAME = 'your_space_name'
11AWS_S3_ENDPOINT_URL = 'spaces_endpoint_URL'
12AWS_S3_OBJECT_PARAMETERS = {
13    'CacheControl': 'max-age=86400',
14}
15AWS_LOCATION = 'static'
16AWS_DEFAULT_ACL = 'public-read'
17
18STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
19
20STATIC_URL = '{}/{}/'.format(AWS_S3_ENDPOINT_URL, AWS_LOCATION)
21STATIC_ROOT = 'static/'

我们定义了以下配置项目:

  • AWS_ACCESS_KEY_ID':您在教学前提中创建的空间访问密钥ID。 如果您没有创建一组访问密钥, 请查阅 [共享访问空间与访问密钥] (https://www.digitalocean.com/docs/spaces/how-to/administrative-access/#access-keys ) 。 *AWS_SECRET_ACESS_KEY': 数字海洋空间的秘密密钥. *`AWS_STORAGE_BUKET_NAME: 你的数码海洋 空间名.
  • AWS_S3_ENDPOINT_URL': 访问对象存储服务的端点 URL. 对于DigitalOcean来说,这将视空间区域而定,类似于https://nyc3.digital Oceanspaces.com'。
  • `AWS_S3_OBJECT_PARAMETERS' 设置静态文件中的缓存控制头。
  • `AWS_LOCATION':在对象存储桶内定义一个目录,所有静态文件将被放置。
  • `AWS_DEFAULT_ACL': 定义静态文件的访问控制列表(ACL)。 将其设置为 " 公众阅读 " ,确保最终用户可公开查阅这些文件。
  • `统计': 设置存储后端 Django 将用来卸载静态文件 。 这个后端应该与任何S3兼容后端相通,包括DigitalOcean Spaces.
  • `STATIC_URL':指定Django在生成静态文件的URL时应当使用的基础URL. 在这里,我们结合了端点 URL 和静态文件子目录来构建静态文件的基础 URL.
  • `STATIC_ROOT':在复制静态文件到对象存储前指定在何地收集 。 (英语)

保存并关闭文件,当你完成编辑。

从现在开始,当你运行collectstatic,Django会将你的应用程序的静态文件上传到空间。

在下一节中,我们将为这个空间启用 CDN,并可选地为 Spaces CDN 配置自定义子域。这将通过在地理分布的边缘服务器网络中缓存 Django 项目的静态文件来加速交付。 有关 CDN 的更多信息,请参阅 使用 CDN 加速静态内容交付

启用 CDN(可选)

要通过 DigitalOcean Spaces CDN 激活静态文件传输,请先启用您的 DigitalOcean Space 的 CDN. 要了解如何做到这一点,请参阅 DigitalOcean 产品文档中的 How to Enable the Spaces CDN

如果您想用 Spaces CDN 使用 自定义域,请按照 如何用子域定制 Spaces CDN 终端点创建子域 CNAME 记录和适当的 SSL 证书。

强烈建议使用 Spaces CDN 的自定义域名,这将大大改善您的网站的搜索引擎优化(SEO),通过将您的资产URL与 Django 网站的 URL 相似。要使用 Spaces CDN 的自定义域名,您需要确保先将您的域名添加到您的 DigitalOcean 帐户。

一旦为您的空间启用了 CDN,并可选地为其创建一个自定义子域,请使用 Cloud 控制面板导航到您的空间。

List of Space Endpoints

如果您为 Spaces CDN 创建了自定义子域,此列表将包含一个名为 Subdomain的额外的终端点。

Edge端点路由请求 Spaces 对象通过 CDN,尽可能地从边缘缓存中提供服务。请记住此 Edge端点,因为我们将使用它来配置django-storages插件。

接下来,重新编辑应用程序的 Django 设置文件:

1nano ~/django-polls/mysite/settings.py

添加AWS_S3_CUSTOM_DOMAIN参数来配置django-storages插件的 CDN 终端,并更新STATIC_URL参数以使用这个新的 CDN 终端:

 1[label ~/django-polls/mysite/settings.py]
 2. . .
 3
 4# Static files (CSS, JavaScript, Images)
 5# https://docs.djangoproject.com/en/2.1/howto/static-files/
 6
 7# Moving static assets to DigitalOcean Spaces as per:
 8# https://andsky.com/tech/tutorials/how-to-set-up-object-storage-with-django
 9AWS_ACCESS_KEY_ID = 'your_spaces_access_key'
10AWS_SECRET_ACCESS_KEY = 'your_spaces_secret_key'
11
12AWS_STORAGE_BUCKET_NAME = 'your_space_name'
13AWS_S3_ENDPOINT_URL = 'spaces_endpoint_URL'
14AWS_S3_CUSTOM_DOMAIN = 'spaces_edge_endpoint_URL'
15AWS_S3_OBJECT_PARAMETERS = {
16    'CacheControl': 'max-age=86400',
17}
18AWS_LOCATION = 'static'
19AWS_DEFAULT_ACL = 'public-read'
20
21STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
22
23STATIC_URL = '{}/{}/'.format(AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
24STATIC_ROOT = 'static/'

例如,如果 Edge 端点 URL 是 https://example.sfo2.cdn.digitaloceanspaces.com,则AWS_S3_CUSTOM_DOMAIN应设置为example.sfo2.cdn.digitaloceanspaces.com

如果您创建了自定义子域,请将spaces_edge_endpoint_URL替换为自定义子域终端,缩小https://前缀,例如,如果子域终端 URL为https://assets.example.com,则AWS_S3_CUSTOM_DOMAIN应设置为assets.example.com

完成后,保存并关闭文件。

当您启动Django时,它将使用CDN为您的DigitalOcean空间提供静态内容。

在我们测试这一切是否正常工作之前,我们需要为我们的 Spaces 文件配置 Cross-Origin Resource Sharing (CORS)标题,或者您的 Web 浏览器可能会拒绝访问某些静态资产。

配置 CORS 头像

CORS 标题告诉 Web 浏览器,一个运行在一个域的应用程序可以访问位于另一个域的脚本或资源. 在这种情况下,我们需要允许我们的 Django 服务器域的跨源资源共享,以便 Web 浏览器不会拒绝对空间中的静态文件的请求。

<$>[注] 注: 此步骤仅在使用 Spaces CDN 的自定义子域时是必要的。

要开始,请使用云控制面板导航到您的空间的设置页面:

Screenshot of the Settings tab

CORS 配置部分中,单击添加

CORS advanced settings

在这里,在 起源下,输入野卡起源, *

<$>[警告] 警告: 当您部署您的应用程序进入生产时,请确保将此值更改为您的确切原始域(包括 http://https:// 协议)。

允许方法下,选择获取

点击添加标题并在出现的文本框中输入访问控制允许来源

Access Control Max Age设置为600,以便我们刚刚创建的标题每10分钟过期。

点击保存选项

从现在开始,您的空间中的对象将包含适当的访问控制允许来源响应标题,允许现代的安全网页浏览器在各个域中检索这些文件。

测试空间静态文件交付

我们现在将测试Django是否正确地从我们的DigitalOcean空间提供静态文件。

导航到您的 Django 应用程序目录:

1cd ~/django-polls

从这里运行collectstatic,收集并上传静态文件到您的DigitalOcean Space:

1python manage.py collectstatic

你应该看到以下结果:

1[secondary_label Output]
2You have requested to collect static files at the destination
3location as specified in your settings.
4
5This will overwrite existing files!
6Are you sure you want to do this?
7
8Type 'yes' to continue, or 'no' to cancel:

输入并点击进入来确认。

然后,你应该看到输出如下

1[secondary_label Output]
2121 static files copied.

这证实了Django成功地将调查应用程序的静态文件上传到您的空间,您可以使用 Cloud 控制面板导航到您的空间,并在静态目录中检查文件。

接下来,我们将检查Django是否正在重写适当的URL。

启动 Gunicorn 服务器:

1gunicorn --bind 0.0.0.0:8000 mysite.wsgi

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

1http://server_domain_or_IP:8000/admin

您应该再次看到调查应用程序管理员身份验证窗口,这次有正确的样式。

现在,使用您的浏览器的开发工具来检查页面内容并揭示源文件存储位置。

若要使用 Google Chrome 进行此操作,请右击页面,然后选择 Inspect

你应该看到以下窗口:

Chrome Dev Tools Window

在左侧窗格的源文件列表中,您应该在您的 Django 服务器的域名下看到 /admin/login,在您的 Space 的 CDN 端点下看到 static/admin。

这确认 CSS 风格表和字体正在正确地从您的 Space 的 CDN 服务。

当你完成测试时,在终端窗口中按CTRL-C来阻止Gunicorn。

您可以通过输入禁用来禁用您的活跃的 Python 虚拟环境:

1deactivate

你的速度应该恢复正常。

在此时刻,您已成功从 Django 服务器下载了静态文件,并正在从对象存储中服务它们。

步骤 8 — 创建 Gunicorn 的 systemd 接口和服务文件

步骤 6中,我们测试了Gunicorn可以与我们的Django应用程序进行交互,但我们应该实施一个更强大的启动和停止应用程序服务器的方式。

Gunicorn 接口将在启动时创建,并会听取连接。当发生连接时,systemd 会自动启动 Gunicorn 过程来处理连接。

首先,创建并打开有sudo特权的 Gunicorn 的 systemd 接口文件:

1sudo nano /etc/systemd/system/gunicorn.socket

内部,我们将创建一个[Unit]部分来描述插槽,一个[Socket]部分来定义插槽的位置,以及一个[Install]部分来确保插槽在正确的时间被创建。

1[label /etc/systemd/system/gunicorn.socket]
2[Unit]
3Description=gunicorn socket
4
5[Socket]
6ListenStream=/run/gunicorn.sock
7
8[Install]
9WantedBy=sockets.target

保存并关闭文件,当你完成。

接下来,在文本编辑器中创建并打开一个用sudo权限的 Gunicorn 的 systemd 服务文件,该服务的文件名应该与插件文件名相匹配,除了扩展:

1sudo nano /etc/systemd/system/gunicorn.service

我们将在这里列出我们的服务的描述,并告诉 init 系统在实现网络目标后才启动此功能。

1[label /etc/systemd/system/gunicorn.service]
2[Unit]
3Description=gunicorn daemon
4Requires=gunicorn.socket
5After=network.target

接下来,我们将打开[服务]部分,我们将指定我们想要处理的用户和组,我们将给我们的常规用户帐户拥有这个过程,因为它拥有所有相关的文件。

然后我们将绘制工作目录并指定要使用的命令来启动服务. 在这种情况下,我们将不得不指定在我们的虚拟环境中安装的Gunicorn可执行的完整路径。我们将将过程绑定到我们在/run目录中创建的Unix插件,以便该过程可以与Nginx进行通信。我们将所有数据记录到标准输出,以便journald过程可以收集Gunicorn日志。

将下列服务部分添加到文件中. 请确保将这里列出的用户名替换为自己的用户名:

 1[label /etc/systemd/system/gunicorn.service]
 2[Unit]
 3Description=gunicorn daemon
 4Requires=gunicorn.socket
 5After=network.target
 6
 7[Service]
 8User=sammy
 9Group=www-data
10WorkingDirectory=/home/sammy/django-polls
11ExecStart=/home/sammy/envs/polls/bin/gunicorn \
12          --access-logfile - \
13          --workers 3 \
14          --bind unix:/run/gunicorn.sock \
15          mysite.wsgi:application

最后,我们将添加一个[安装]部分,这将告诉系统d如果我们允许该服务在启动时启动,该服务将连接到什么。

 1[label /etc/systemd/system/gunicorn.service]
 2[Unit]
 3Description=gunicorn daemon
 4Requires=gunicorn.socket
 5After=network.target
 6
 7[Service]
 8User=sammy
 9Group=www-data
10WorkingDirectory=/home/sammy/django-polls
11ExecStart=/home/sammy/envs/polls/bin/gunicorn \
12          --access-logfile - \
13          --workers 3 \
14          --bind unix:/run/gunicorn.sock \
15          mysite.wsgi:application
16
17[Install]
18WantedBy=multi-user.target

这样,我们的 systemd 服务文件就完成了. 现在保存并关闭它。

我们现在可以启动并启用 Gunicorn 接口,这将创建在 `/run/gunicorn.sock’ 和启动时的接口文件。

1sudo systemctl start gunicorn.socket
2sudo systemctl enable gunicorn.socket

我们可以通过检查插件文件来确认操作成功。

查找 Gunicorn Socket 文件

检查过程的状态,看看它是否成功启动:

1sudo systemctl status gunicorn.socket

你应该看到以下结果:

1[secondary_label Output]
2Failed to dump process list, ignoring: No such file or directory
3 gunicorn.socket - gunicorn socket
4   Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled)
5   Active: active (running) since Tue 2019-03-05 19:19:16 UTC; 1h 22min ago
6   Listen: /run/gunicorn.sock (Stream)
7   CGroup: /system.slice/gunicorn.socket
8
9Mar 05 19:19:16 django systemd[1]: Listening on gunicorn socket.

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

1file /run/gunicorn.sock
1[secondary_label Output]
2/run/gunicorn.sock: socket

如果systemctl status命令表明出现了错误,或者您在目录中找不到gunicorn.sock文件,这表明 Gunicorn 接口没有正确创建。

1sudo journalctl -u gunicorn.socket

再看看您的 /etc/systemd/system/gunicorn.socket 文件,在继续之前修复任何问题。

测试 Socket 激活

目前,如果您刚刚启动了gunicorn.socket单元,则gunicorn.service将不会活跃,因为插件尚未接收任何连接。

1sudo systemctl status gunicorn
1[secondary_label Output]
2 gunicorn.service - gunicorn daemon
3   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
4   Active: inactive (dead)

要测试插槽激活机制,我们可以通过键入弯曲发送连接到插槽:

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

您应该在终端中看到您的应用程序的HTML输出。这表明Gunicorn已经启动并能够服务您的Django应用程序。您可以通过键入来验证Gunicorn服务正在运行:

1sudo systemctl status gunicorn
 1[secondary_label Output]
 2 gunicorn.service - gunicorn daemon
 3   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
 4   Active: active (running) since Tue 2019-03-05 20:43:56 UTC; 1s ago
 5 Main PID: 19074 (gunicorn)
 6    Tasks: 4 (limit: 4915)
 7   CGroup: /system.slice/gunicorn.service
 8           ├─19074 /home/sammy/envs/polls/bin/python3 /home/sammy/envs/polls/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock mysite.wsgi:application
 9           ├─19098 /home/sammy/envs/polls/bin/python3 /home/sammy/envs/polls/bin/gunicorn 
10. . .
11
12Mar 05 20:43:56 django systemd[1]: Started gunicorn daemon.
13Mar 05 20:43:56 django gunicorn[19074]: [2019-03-05 20:43:56 +0000] [19074] [INFO] Starting gunicorn 19.9.0
14. . .
15Mar 05 20:44:15 django gunicorn[19074]:  - - [05/Mar/2019:20:44:15 +0000] "GET / HTTP/1.1" 301 0 "-" "curl/7.58.0"

如果从弯曲的输出或systemctl 状态的输出表明出现问题,请检查日志以获取更多细节:

1sudo journalctl -u gunicorn

您还可以检查您的 /etc/systemd/system/gunicorn.service 文件是否存在问题. 如果您对此文件进行更改,请确保重新加载 DAEMON 来重新阅读服务定义并重新启动 Gunicorn 过程:

1sudo systemctl daemon-reload
2sudo systemctl restart gunicorn

请确保在继续配置 Nginx 服务器之前解决任何问题。

步骤 8 — 配置 Nginx HTTPS 和 Gunicorn 代理传输

现在Gunicorn以更强大的方式设置,我们需要配置 Nginx来加密连接并将流量转移到Gunicorn流程中。

如果你遵循了前提条件并使用 Let’s Encrypt 设置了 Nginx,那么你应该已经在 Nginx 的 可用网站 目录中拥有一个服务器封锁文件,相应于你的域名,否则请遵循 Ubuntu 18.04 上的 How To Secure Nginx with Let’s Encrypt )并返回此步骤。

在我们编辑此example.com服务器封锁文件之前,我们首先将删除安装 Nginx 后默认发布的默认服务器封锁文件:

1sudo rm /etc/nginx/sites-enabled/default

我们现在将修改example.com服务器封锁文件以将流量传送到Gunicorn,而不是在前提步骤中配置的默认index.html页面。

在您的编辑器中打开相应的服务器封锁文件:

1sudo nano /etc/nginx/sites-available/example.com

你应该看到一些如下:

 1[label /etc/nginx/sites-available/example.com]
 2server {
 3
 4        root /var/www/example.com/html;
 5        index index.html index.htm index.nginx-debian.html;
 6
 7        server_name example.com www.example.com;
 8
 9        location / {
10                try_files $uri $uri/ =404;
11        }
12
13    listen [::]:443 ssl ipv6only=on; # managed by Certbot
14    listen 443 ssl; # managed by Certbot
15    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
16    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
17    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
18    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
19
20}
21
22server {
23    if ($host = example.com) {
24        return 301 https://$host$request_uri;
25    } # managed by Certbot
26
27        listen 80;
28        listen [::]:80;
29
30        server_name example.com www.example.com;
31    return 404; # managed by Certbot
32
33}

这是在 [How to Install Nginx on Ubuntu 18.04](https://andsky.com/tech/tutorials/how-to-install-nginx-on-ubuntu-18-04#step-5-setting-up-server-blocks-(recommended)中创建的默认服务器封锁文件的组合,以及由 Let's Encrypt 自动附加的附加文件。

如果你愿意,你可以使用cp来备份这个文件,关闭文本编辑器并创建一个名为example.com.old的备份:

1sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.old

现在,重新打开文件并删除其内容,我们将每块构建一个新的配置块。

首先,将 HTTP 请求从端口 `80 重定向到 HTTPS:

1[label /etc/nginx/sites-available/example.com]
2server {
3    listen 80 default_server;
4    listen [::]:80 default_server;
5    server_name _;
6    return 301 https://example.com$request_uri;
7}

在这里,我们在端口80上聆听HTTP IPv4和IPv6请求,并发送301响应头,将请求重定向到HTTPS端口443使用example.com域。

在此区块之后,附上下列配置代码区块,以处理 example.com 域的 HTTPS 请求:

 1[label /etc/nginx/sites-available/example.com]
 2. . . 
 3server {
 4    listen [::]:443 ssl ipv6only=on;
 5    listen 443 ssl;
 6    server_name example.com www.example.com;
 7    
 8    # Let's Encrypt parameters
 9    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
10    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
11    include /etc/letsencrypt/options-ssl-nginx.conf;
12    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
13    
14    location = /favicon.ico { access_log off; log_not_found off; }
15
16    location / {
17        proxy_pass http://unix:/run/gunicorn.sock;
18        proxy_redirect off;
19
20        proxy_set_header Host              $http_host;
21        proxy_set_header X-Real-IP         $remote_addr;
22        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
23        proxy_set_header X-Forwarded-Proto https;
24    }
25}

在这里,我们首先听到443端口对点击example.comwww.example.com域的请求。

接下来,我们提供了默认服务器封锁文件中包含的相同的 Let's Encrypt 配置,该配置指定了 SSL 证书和私钥的位置,以及一些额外的安全参数。

位置 = /favicon.ico 行指示 Nginx 忽略找到 favicon 的任何问题。

最后一个位置 = /块指示 Nginx 将请求发送到在 步骤 8中配置的 Gunicorn 接口。

在插入这两个配置块后,最终的文件应该看起来像这样:

 1[label /etc/nginx/sites-available/example.com]
 2server {
 3    listen 80 default_server;
 4    listen [::]:80 default_server;
 5    server_name _;
 6    return 301 https://example.com$request_uri;
 7}
 8server {
 9        listen [::]:443 ssl ipv6only=on;
10        listen 443 ssl;
11        server_name example.com www.example.com;
12
13        # Let's Encrypt parameters
14        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
15        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
16        include /etc/letsencrypt/options-ssl-nginx.conf;
17        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
18
19        location = /favicon.ico { access_log off; log_not_found off; }
20
21        location / {
22          proxy_pass http://unix:/run/gunicorn.sock;
23          proxy_redirect off;
24
25          proxy_set_header Host              $http_host;
26          proxy_set_header X-Real-IP         $remote_addr;
27          proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
28          proxy_set_header X-Forwarded-Proto https;
29        }
30}

保存并关闭文件,当你完成。

通过键入测试您的 Nginx 配置以检测语法错误:

1sudo nginx -t

如果您的配置没有错误,请通过键入重新启动 Nginx:

1sudo systemctl restart nginx

您现在应该能够访问您的服务器的域名或 IP 地址来查看您的应用程序. 您的浏览器应该使用安全的 HTTPS 连接连接到 Django 后端。

为了完全保护我们的 Django 项目,我们需要将一些安全参数添加到其 settings.py 文件中。

1nano ~/django-polls/mysite/settings.py

滚到文件的底部,并添加以下参数:

1[label ~/django-polls/mysite/settings.py]
2. . .
3
4SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
5SESSION_COOKIE_SECURE = True
6CSRF_COOKIE_SECURE = True
7SECURE_SSL_REDIRECT = True

这些设置告诉 Django 您已在您的服务器上启用 HTTPS,并指示它使用安全 Cookie。 有关这些设置的更多信息,请参阅 SSL/HTTPS 部分Security in Django

完成后,保存并关闭文件。

最后,重新启动 Gunicorn:

1sudo systemctl restart gunicorn

此时,您已配置 Nginx 来重定向 HTTP 请求,并将这些请求交给 Gunicorn. HTTPS 现在应该为您的 Django 项目和应用程序完全启用。

<$>[警告] 警告: 如果您没有**配置 Spaces CDN 的自定义子域,如在 ** Configuring CORS Headers**中所述,请确保将 Origin从 wildcard * 域名更改为您的域名(https://example.com 在本指南中),然后让您的应用程序可供最终用户访问。

结论

在本指南中,您已设置并配置了一个可扩展的Django应用程序,运行在Ubuntu 18.04服务器上。此设置可以在多个服务器上复制,以创建一个高度可用的架构。此外,该应用程序及其配置可以使用Docker(http://nginx.org/en/docs/http/configuring_https_servers.html)或其他容器运行时间进行集装,以便简化部署和扩展。这些容器可以部署到一个容器集群中,例如Kubernetes(https://kubernetes.io/)。

除了静态文件外,您还可能希望将 Django Media 文件下载到对象存储中。 要了解如何做到这一点,请参阅 使用 Amazon S3 来存储 Django 网站的静态和媒体文件

Published At
Categories with 技术
comments powered by Disqus