如何在Ubuntu14.04上使用uWSGI和Nginx服务Django应用程序
介绍
Django 是一个强大的 Web 框架,可以帮助您启动 Python 应用程序或网站。 Django 包含一个简化的开发服务器,用于在本地测试您的代码,但对于任何与生产相关的事情,都需要一个更安全、更强大的 Web 服务器。
在本指南中,我们将演示如何在 Ubuntu 14.04 上安装和配置一些组件以支持和服务 Django 应用程序。 我们将配置 uWSGI 应用程序容器服务器以与我们的应用程序交互。 然后,我们将设置 Nginx 以反向代理到 uWSGI,使我们能够访问其安全性和性能特性来为我们的应用程序提供服务。
先决条件和目标
为了完成本指南,您应该拥有一个全新的 Ubuntu 14.04 服务器实例,其中包含配置了 sudo
权限的非 root 用户。 您可以通过我们的 初始服务器设置指南 来了解如何设置它。
我们将在两个不同的虚拟环境中安装 Django。 这将允许单独处理您的项目及其要求。 我们将创建两个示例项目,以便我们可以在多项目环境中运行这些步骤。
一旦我们有了我们的应用程序,我们将安装和配置 uWSGI 应用程序服务器。 这将作为我们应用程序的接口,它将使用 HTTP 的客户端请求转换为我们的应用程序可以处理的 Python 调用。 然后,我们将在 uWSGI 前面设置 Nginx,以利用其高性能的连接处理机制和易于实现的安全特性。
让我们开始吧。
安装和配置 VirtualEnv 和 VirtualEnvWrapper
我们将在他们自己的虚拟环境中安装我们的 Django 项目,以隔离每个项目的需求。 为此,我们将安装 virtualenv
,它可以创建 Python 虚拟环境,以及 virtualenvwrapper
,它为 virtualenv
工作流程增加了一些可用性改进。
我们将使用 Python 包管理器 pip
安装这两个组件。 这可以从 Ubuntu 存储库中获取:
sudo apt-get update sudo apt-get install python-pip
在本指南中,我们使用的是 Python 版本 2。 如果您的代码使用 Python 3,您可以安装 python3-pip
包。 在虚拟环境之外操作时,您必须将本指南中的 pip
命令替换为 pip3
命令。
现在您已经安装了 pip
,我们可以通过键入以下命令全局安装 virtualenv
和 virtualenvwrapper
:
sudo pip install virtualenv virtualenvwrapper
安装这些组件后,我们现在可以使用 virtualenvwrapper
脚本所需的信息来配置我们的 shell。 我们的虚拟环境都将放置在我们的主文件夹中名为 Env
的目录中,以便于访问。 这是通过一个名为 WORKON_HOME
的环境变量来配置的。 我们可以将它添加到我们的 shell 初始化脚本中,并且可以获取虚拟环境包装器脚本。
如果您使用的是 Python 3 和 pip3
命令,则还必须在 shell 初始化脚本中添加一行:
echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc
无论您使用的是哪个版本的 Python,您都需要运行以下命令:
echo "export WORKON_HOME=~/Env" >> ~/.bashrc echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc
现在,获取您的 shell 初始化脚本,以便您可以在当前会话中使用此功能:
source ~/.bashrc
您现在应该在您的主文件夹中有一个名为 Env
的目录,该目录将保存虚拟环境信息。
创建 Django 项目
现在我们有了虚拟环境工具,我们将创建两个虚拟环境,在每个环境中安装 Django,并启动两个项目。
创建第一个项目
我们可以使用 virtualenvwrapper
脚本提供给我们的一些命令轻松创建虚拟环境。
通过键入以下内容,使用您的第一个站点或项目的名称创建您的第一个虚拟环境:
mkvirtualenv firstsite
这将创建一个虚拟环境,在其中安装 Python 和 pip
,并激活环境。 您的提示将更改以指示您现在正在新的虚拟环境中操作。 它看起来像这样:(firstsite)user@hostname:~$
。 括号中的值是您的虚拟环境的名称。 通过 pip
安装的任何软件现在都将安装到虚拟环境中,而不是安装在全局系统中。 这允许我们在每个项目的基础上隔离我们的包。
我们的第一步是安装 Django 本身。 我们可以在没有 sudo
的情况下使用 pip
,因为我们是在虚拟环境中本地安装它:
pip install django
安装 Django 后,我们可以通过键入以下内容创建我们的第一个示例项目:
cd ~ django-admin.py startproject firstsite
这将在您的主目录中创建一个名为 firstsite
的目录。 其中有一个用于处理项目各个方面的管理脚本和另一个用于存放实际项目代码的同名目录。
移动到第一级目录,以便我们可以开始设置示例项目的最低要求。
cd ~/firstsite
首先迁移数据库以初始化我们项目将使用的 SQLite 数据库。 如果您愿意,您可以为您的应用程序设置一个备用数据库,但这超出了本指南的范围:
./manage.py migrate
您现在应该在项目目录中有一个名为 db.sqlite3
的数据库文件。 现在,我们可以通过键入以下内容来创建管理用户:
./manage.py createsuperuser
您必须选择用户名,提供联系电子邮件地址,然后选择并确认密码。
接下来,使用文本编辑器打开项目的设置文件:
nano firstsite/settings.py
由于我们将设置 Nginx 来为我们的网站提供服务,我们需要配置一个目录来保存我们网站的静态资产。 这将允许 Nginx 直接为这些服务,这将对性能产生积极影响。 我们将告诉 Django 将它们放入项目基目录中名为 static
的目录中。 将此行添加到文件底部以配置此行为:
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
完成后保存并关闭文件。 现在,收集我们网站的静态元素并将它们放在该目录中,输入:
./manage.py collectstatic
您可以键入“是”以确认操作并收集静态内容。 在您的项目目录中将有一个名为 static
的新目录。
完成所有这些后,我们可以通过临时启动开发服务器来测试我们的项目。 类型:
./manage.py runserver 0.0.0.0:8080
这将在端口 8080
上启动开发服务器。 在浏览器中访问您服务器的域名或 IP 地址,后跟 8080
:
http://server_domain_or_IP:8080
您应该会看到如下所示的页面:
将 /admin
添加到浏览器地址栏中 URL 的末尾,您将被带到管理员登录页面:
使用您通过 createsuperuser
命令选择的管理登录凭据,登录到服务器。 然后,您将可以访问管理界面:
测试此功能后,在终端中键入 CTRL-C 停止开发服务器。 我们现在可以继续我们的第二个项目。
创建第二个项目
第二个项目的创建方式与第一个项目完全相同。 我们将在本节中删减解释,看看您是如何完成这一次的。
回到您的主目录并为您的新项目创建第二个虚拟环境。 激活后在这个新环境中安装 Django:
cd ~ mkvirtualenv secondsite pip install django
将创建新环境 并将 更改为,保留您以前的虚拟环境。 这个 Django 实例与您配置的另一个实例完全分开。 这使您可以独立管理它们并根据需要进行自定义。
创建第二个项目并进入项目目录:
django-admin.py startproject secondsite cd ~/secondsite
初始化数据库并创建一个管理用户:
./manage.py migrate ./manage.py createsuperuser
打开设置文件:
nano secondsite/settings.py
添加静态文件的位置,就像您在上一个项目中所做的那样:
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
保存并关闭文件。 现在,通过键入以下命令将静态元素收集到该目录中:
./manage.py collectstatic
最后,启动开发服务器来测试站点:
./manage.py runserver 0.0.0.0:8080
您应该在以下网址查看常规网站:
http://server_domain_or_IP:8080
同时登录管理站点:
http://server_domain_or_IP:8080/admin
当您确认一切都按预期工作时,在您的终端中键入 CTRL-C 以停止开发服务器。
退出虚拟环境
由于我们现在已经完成了指南的 Django 部分,我们可以停用我们的第二个虚拟环境:
deactivate
如果您需要再次在任一 Django 站点上工作,您应该重新激活它们各自的环境。 您可以使用 workon
命令来做到这一点:
workon firstsite
或者:
workon secondsite
同样,在您完成网站工作后停用:
deactivate
设置 uWSGI 应用服务器
现在我们已经设置了两个 Django 项目并准备就绪,我们可以配置 uWSGI。 uWSGI 是一个应用服务器,可以通过称为 WSGI 的标准接口与应用程序进行通信。 要了解更多信息,请阅读我们在 Ubuntu 14.04 上设置 uWSGI 和 Nginx 指南的 本节 。
安装 uWSGI
与上面链接的指南不同,在本教程中,我们将全局安装 uWSGI。 这将在处理多个 Django 项目时减少摩擦。 在我们安装 uWSGI 之前,我们需要软件所依赖的 Python 开发文件。 我们可以直接从 Ubuntu 的存储库中安装它:
sudo apt-get install python-dev
现在开发文件可用,我们可以通过 pip
全局安装 uWSGI,输入:
sudo pip install uwsgi
我们可以通过将我们的站点之一的信息传递给它来快速测试这个应用程序服务器。 例如,我们可以通过键入以下命令告诉它为我们的第一个项目服务:
uwsgi --http :8080 --home /home/user/Env/firstsite --chdir /home/user/firstsite -w firstsite.wsgi
在这里,我们告诉 uWSGI 使用位于我们的 ~/Env
目录中的虚拟环境,切换到我们的项目目录,并使用存储在我们内部 [X186X 中的 wsgi.py
文件] 目录来提供文件。 对于我们的演示,我们告诉它在端口 8080
上提供 HTTP。 如果您在浏览器中访问服务器的域名或 IP 地址,然后输入 :8080
,您将再次看到您的站点(/admin
界面中的静态元素还不能工作)。 完成此功能的测试后,在终端中键入 CTRL-C。
创建配置文件
从命令行运行 uWSGI 对于测试很有用,但对于实际部署并不是特别有用。 相反,我们将在“Emperor 模式”下运行 uWSGI,它允许主进程在给定一组配置文件的情况下自动管理单独的应用程序。
创建一个存放配置文件的目录。 由于这是一个全局进程,我们将创建一个名为 /etc/uwsgi/sites
的目录来存储我们的配置文件。 创建后进入目录:
sudo mkdir -p /etc/uwsgi/sites cd /etc/uwsgi/sites
在这个目录中,我们将放置我们的配置文件。 我们需要为我们服务的每个项目提供一个配置文件。 uWSGI 进程可以采用多种格式的配置文件,但由于其简单性,我们将使用 .ini
文件。
为您的第一个项目创建一个文件并在文本编辑器中打开它:
sudo nano firstsite.ini
在内部,我们必须从 [uwsgi]
节标题开始。 我们所有的信息都将放在此标题下方。 我们还将使用变量来使我们的配置文件更可重用。 在标题之后,使用您的第一个项目的名称设置一个名为 project
的变量。 添加一个名为 base
的变量,其中包含用户主目录的路径:
[uwsgi] project = firstsite base = /home/user
接下来,我们需要配置 uWSGI 以便它正确处理我们的项目。 我们需要通过设置 chdir
选项进入项目根目录。 我们可以使用 %(variable_name)
语法来组合我们之前设置的主目录和项目名称设置。 读取配置时,这将被变量的值替换。
以类似的方式,我们将为我们的项目指明虚拟环境。 通过设置模块,我们可以准确地指示如何与我们的项目交互(通过从项目目录中的 wsgi.py
文件中导入可调用的“应用程序”)。 这些项目的配置将如下所示:
[uwsgi] project = firstsite base = /home/user chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application
我们想创建一个有 5 个工作人员的主进程。 我们可以通过添加这个来做到这一点:
[uwsgi] project = firstsite base = /home/user chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application master = true processes = 5
接下来我们需要指定 uWSGI 应该如何监听连接。 在我们对 uWSGI 的测试中,我们使用了 HTTP 和一个网络端口。 但是,由于我们将使用 Nginx 作为反向代理,因此我们有更好的选择。
我们可以使用 Unix 套接字,而不是使用网络端口,因为所有组件都在单个服务器上运行。 这更安全并提供更好的性能。 这个套接字不会使用 HTTP,而是会实现 uWSGI 的 uwsgi
协议,这是一种用于与其他服务器通信的快速二进制协议。 Nginx 可以使用 uwsgi
协议进行原生代理,所以这是我们最好的选择。
我们还将修改套接字的权限,因为我们将授予 Web 服务器写入权限。 我们将设置 vacuum
选项,以便在服务停止时自动清理套接字文件:
[uwsgi] project = firstsite base = /home/user chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application master = true processes = 5 socket = %(base)/%(project)/%(project).sock chmod-socket = 664 vacuum = true
至此,我们第一个项目的uWSGI配置就完成了。 保存并关闭文件。
使用变量设置文件的优点是它使重用变得非常简单。 复制您的第一个项目的配置文件以用作您的第二个配置文件的基础:
sudo cp /etc/uwsgi/sites/firstsite.ini /etc/uwsgi/sites/secondsite.ini
使用文本编辑器打开第二个配置文件:
sudo nano /etc/uwsgi/sites/secondsite.ini
我们只需要更改此文件中的单个值即可使其适用于我们的第二个项目。 使用您在第二个项目中使用的名称修改 project
变量:
[uwsgi] project = secondsite base = /home/user chdir = %(base)/%(project) home = %(base)/Env/%(project) module = %(project).wsgi:application master = true processes = 5 socket = %(base)/%(project)/%(project).sock chmod-socket = 664 vacuum = true
完成后保存并关闭文件。 您的第二个项目现在应该可以开始了。
为 uWSGI 创建 Upstart 脚本
我们现在有了为 Django 项目提供服务所需的配置文件,但我们还没有自动化这个过程。 接下来,我们将创建一个 Upstart 脚本以在启动时自动启动 uWSGI。
我们将在 /etc/init
目录中创建一个 Upstart 脚本,检查这些文件:
sudo nano /etc/init/uwsgi.conf
首先为您的 uWSGI 服务设置描述并指明它应该自动运行的运行级别。 我们将设置我们的运行级别 2、3、4 和 5,它们是传统的多用户运行级别:
description "uWSGI application server in Emperor mode" start on runlevel [2345] stop on runlevel [!2345]
接下来,我们需要设置进程将运行的用户名和组。 由于我们拥有所有文件,因此我们将使用自己的用户名运行该过程。 对于组,我们需要将其设置为 Nginx 将在其下运行的 www-data
组。 然后,我们来自 uWSGI 配置文件的套接字设置应该允许 Web 服务器写入套接字。 更改下面的用户名以匹配您在服务器上的用户名:
description "uWSGI application server in Emperor mode" start on runlevel [2345] stop on runlevel [!2345] setuid user setgid www-data
最后,我们需要指定要执行的实际命令。 我们需要以 Emperor 模式启动 uWSGI 并传入我们存储配置文件的目录。 uWSGI 将读取文件并为我们的每个项目提供服务:
description "uWSGI application server in Emperor mode" start on runlevel [2345] stop on runlevel [!2345] setuid user setgid www-data exec /usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
完成后,保存并关闭文件。 我们还不会启动 uWSGI,因为在我们安装 Nginx 之前,我们将没有可用的 www-data
组。
安装和配置 Nginx 作为反向代理
配置好 uWSGI 并准备就绪后,我们现在可以安装和配置 Nginx 作为我们的反向代理。 这可以从 Ubuntu 的默认存储库下载:
sudo apt-get install nginx
安装 Nginx 后,我们可以继续为每个项目创建一个服务器块配置文件。 通过创建服务器块配置文件从第一个项目开始:
sudo nano /etc/nginx/sites-available/firstsite
在内部,我们可以通过指示我们的第一个项目应该可以访问的端口号和域名来启动我们的服务器块。 我们假设您有一个域名:
server { listen 80; server_name firstsite.com www.firstsite.com; }
接下来,如果 Nginx 找不到 favicon,我们可以告诉它不要担心。 我们还将它指向我们收集站点静态元素的静态文件目录的位置:
server { listen 80; server_name firstsite.com www.firstsite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/user/firstsite; } }
之后,我们可以使用 uwsgi_pass
指令将流量传递给我们的套接字文件。 我们配置的套接字文件名为 firstproject.sock
,它位于我们的项目目录中。 我们将使用 include
指令来包含必要的 uwsgi
参数来处理连接:
server { listen 80; server_name firstsite.com www.firstsite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/user/firstsite; } location / { include uwsgi_params; uwsgi_pass unix:/home/user/firstsite/firstsite.sock; } }
这实际上就是我们需要的所有配置。 完成后保存并关闭文件。
我们将以此作为第二个项目的 Nginx 配置文件的基础。 现在复制过来:
sudo cp /etc/nginx/sites-available/firstsite /etc/nginx/sites-available/secondsite
在文本编辑器中打开新文件:
sudo nano /etc/nginx/sites-available/secondsite
在这里,您必须将对 firstsite
的任何引用更改为对 secondsite
的引用。 您还必须修改 server_name
以便您的第二个项目响应不同的域名。 完成后,它将如下所示:
server { listen 80; server_name secondsite.com www.secondsite.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/user/secondsite; } location / { include uwsgi_params; uwsgi_pass unix:/home/user/secondsite/secondsite.sock; } }
完成后保存并关闭文件。
接下来,将两个新配置文件链接到 Nginx 的 sites-enabled
目录以启用它们:
sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled sudo ln -s /etc/nginx/sites-available/secondsite /etc/nginx/sites-enabled
通过键入以下内容检查配置语法:
sudo service nginx configtest
如果未检测到语法错误,您可以重新启动 Nginx 服务以加载新配置:
sudo service nginx restart
如果您还记得之前的内容,我们实际上从未启动过 uWSGI 服务器。 现在通过键入:
sudo service uwsgi start
您现在应该能够通过访问它们各自的域名来访问您的两个项目。 公共和管理界面都应该按预期工作。
结论
在本指南中,我们设置了两个 Django 项目,每个项目都在自己的虚拟环境中。 我们已经将 uWSGI 配置为使用为每个项目配置的虚拟环境独立地为每个项目提供服务。 之后,我们设置 Nginx 作为反向代理来处理客户端连接并根据客户端请求为正确的项目提供服务。
Django 通过提供许多通用部分使创建项目和应用程序变得简单,让您可以专注于独特的元素。 通过利用本文中描述的通用工具链,您可以轻松地为您从单个服务器创建的应用程序提供服务。