如何在Ubuntu14.04上使用uWSGI和Nginx部署Web2pyPython应用程序

来自菜鸟教程
跳转至:导航、​搜索

介绍

web2py 框架是一个功能强大且易于使用的工具,用于快速开发功能齐全的 Python Web 应用程序。 使用 web2py,您可以通过使用管理 Web UI 轻松开发和管理您的应用程序。

在本指南中,我们将演示如何在 Ubuntu 14.04 上部署 web2py 应用程序。 我们将使用 uWSGI 应用程序服务器与具有多个工作进程的应用程序进行交互。 在 uWSGI 前面,我们将在反向代理配置中设置 Nginx 来处理实际的客户端连接。 这是一种比单独使用 web2py 服务器或 uWSGI 更强大的部署策略。

先决条件和目标

为了完成本指南,您应该拥有一个全新的 Ubuntu 14.04 服务器实例,其中包含配置了 sudo 权限的非 root 用户。 您可以通过我们的 初始服务器设置指南 来了解如何设置它。

我们将下载 web2py 框架并对其进行测试,以确保默认应用程序环境正常运行。 之后,我们将下载并安装 uWSGI 应用程序容器,作为请求和 web2py Python 代码之间的接口。 我们将在此之前设置 Nginx,以便它可以处理客户端连接和对 uWSGI 的代理请求。 我们将配置我们的每个组件以在启动时启动,以最大限度地减少管理干预的需要。

下载 web2py 框架

我们的第一步是下载实际的 web2py 框架。 这是在 GitHub 上的 git 存储库中维护的,因此下载它的最佳方式是使用 git 本身。

我们可以通过键入以下命令从默认的 Ubuntu 存储库下载并安装 git

sudo apt-get update
sudo apt-get install git

安装 git 后,我们可以将存储库克隆到用户的主目录。 我们可以随意命名应用程序。 在我们的示例中,为简单起见,我们使用名称 myapp。 我们需要添加 --recursive 标志,因为数据库抽象层作为其自己的 git 子模块处理:

git clone --recursive https://github.com/web2py/web2py.git ~/myapp

web2py 框架将被下载到您的主目录中名为 myapp 的目录中。

我们可以通过移动到目录来测试默认应用程序:

cd ~/myapp

管理界面必须由 SSL 保护,因此我们可以制作一个简单的自签名证书来测试这一点。 通过键入以下内容创建服务器密钥和证书:

openssl req -x509 -new -newkey rsa:4096 -days 3652 -nodes -keyout myapp.key -out myapp.crt

您必须为要生成的证书填写一些信息。 在这种情况下,唯一真正重要的部分是 Common Name 字段,它应该引用您服务器的域名或 IP 地址:

. . .

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DigitalOcean
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:server_domain_or_IP
Email Address []:admin@email.com

完成后,SSL 密钥和证书应该在您的应用程序目录中。 这些将分别称为 myapp.keymyapp.crt

完成后,我们可以启动 web2py Web 界面来测试它。 为此,我们可以键入:

python web2py.py -k myapp.key -c myapp.crt -i 0.0.0.0 -p 8000

系统将要求您选择管理界面的密码。

现在,您可以在 Web 浏览器中访问您的应用程序,方法是导航到:

https://server_domain_or_IP:8000

确保在上述地址中使用 https 而不是 http。 您将收到警告,您的浏览器无法识别 SSL 证书:

这是意料之中的,因为我们已经签署了自己的证书。 单击“高级”链接或浏览器提供的任何其他链接,然后按计划继续访问该站点。 您将看到 web2py 界面:

通过点击最右侧的“管理界面”按钮,您应该能够输入您在运行服务器时选择的密码并进入管理站点:

这使您可以访问运行应用程序的实际代码,允许您从界面本身编辑和调整文件。

环顾四周后,在终端窗口中键入 CTRL-C。 我们已经测试了我们的应用程序,并证明当 web2py 开发服务器运行时,它可以在 Web 上访问。

安装和配置 uWSGI

现在我们已经可以运行 web2py 应用程序,我们可以配置 uWSGI。 uWSGI 是一个应用服务器,可以通过称为 WSGI 的标准接口与应用程序进行通信。 要了解更多信息,请阅读我们在 Ubuntu 14.04 上设置 uWSGI 和 Nginx 指南的 本节

安装 uWSGI

与上面链接的指南不同,在本教程中,我们将全局安装 uWSGI。 在我们安装 uWSGI 之前,我们需要安装 pip、Python 包管理器和 uWSGI 所依赖的 Python 开发文件。 我们可以直接从 Ubuntu 的存储库中安装这些:

sudo apt-get install python-pip python-dev

现在我们可以通过输入 pip 全局安装 uWSGI:

sudo pip install uwsgi

uWSGI 应用程序容器服务器使用 WSGI 接口规范与 Python 应用程序接口。 web2py 框架在其 handlers 目录中包含一个旨在提供此接口的文件。 要使用该文件,我们需要将其移出目录并进入主项目目录:

mv ~/myapp/handlers/wsgihandler.py ~/myapp

使用主项目目录中的 WSGI 处理程序,我们可以通过键入以下内容来检查 uWSGI 是否能够为应用程序提供服务:

uwsgi --http :8000 --chdir ~/myapp -w wsgihandler:application

这应该会在端口 8000 上再次启动应用程序。 这一次,由于我们没有使用 SSL 证书和密钥,它将通过纯 HTTP 而不是 HTTPS 提供服务。 您可以使用 http 协议在浏览器中再次进行测试。 您将无法测试管理界面,因为 web2py 在加密不可用时会禁用此功能。

完成后,在终端窗口中键入 CTRL-C 以停止服务器。

创建 uWSGI 配置文件

现在我们知道 uWSGI 可以为应用程序提供服务,我们可以使用应用程序的信息创建一个 uWSGI 配置文件。

/etc/uwsgi/sites 创建一个目录来存储我们的配置,然后进入该目录:

sudo mkdir -p /etc/uwsgi/sites
cd /etc/uwsgi/sites

我们将调用我们的配置文件 myapp.ini

sudo nano myapp.ini

在配置文件中,我们需要从一个 [uwsgi] 标题开始,我们所有的配置指令都将放置在该标题下。 在标头之后,我们将指示应用程序的目录路径,并告诉它要执行的模块。 这将与我们之前在命令行中使用的信息相同。 您不需要修改模块行:

[uwsgi]
chdir = /home/user/myapp
module = wsgihandler:application

接下来,我们需要指定我们希望 uWSGI 在主模式下运行。 我们想产生五个工作进程:

[uwsgi]
chdir = /home/user/myapp
module = wsgihandler:application

master = true
processes = 5

接下来,我们需要指定我们希望 uWSGI 如何获取连接。 在我们对 uWSGI 服务器的测试中,我们接受了正常的 HTTP 连接。 但是,由于我们将在 uWSGI 之前将 Nginx 配置为反向代理,因此我们还有其他选择。 Nginx 可以使用 uwsgi 协议进行代理,这是一种由 uWSGI 设计的用于与其他服务器通信的快速二进制协议。 我们将使用此协议进行通信,如果我们不指定其他协议,这是默认的。

由于我们使用 uwsgi 协议与 Nginx 通信,因此我们不需要网络端口。 相反,我们将使用更安全、更快速的 Unix 套接字。 我们将把它放在我们的应用程序目录中。 我们需要修改权限,以便组可以读取和写入套接字。 稍后,我们将授予 Nginx 进程组对套接字的所有权,以便 uWSGI 和 Nginx 可以通过套接字进行通信:

[uwsgi]
chdir = /home/user/myapp
module = wsgihandler:application

master = true
processes = 5

socket = /home/user/myapp/myapp.sock
chmod-socket = 660
vacuum = true

上面的 vacuum 指令将在 uWSGI 进程结束时清理套接字文件。

我们的 uWSGI 配置文件现在已经完成。 保存并关闭文件。

创建一个 uWSGI Upstart 文件

我们已经为 uWSGI 创建了一个配置文件,但是我们还没有将我们的应用服务器设置为在启动时自动启动。 为了实现这个功能,我们可以创建一个简单的 Upstart 文件。 我们将告诉它以“Emperor 模式”运行 uWSGI,这允许应用程序服务器读取任意数量的配置并为每个配置启动服务器。

在 Upstart 进程查找其配置文件的 /etc/init 目录中创建一个文件:

sudo nano /etc/init/uwsgi.conf

我们将首先给我们的服务文件一个描述,并指出我们希望在哪些运行级别上自动启动它。 传统的多用户运行级别是 2、3、4 和 5。 当服务器进入其他运行级别时(例如在关机、重新启动或单用户模式期间),我们将让 Upstart 停止服务:

description "uWSGI application server in Emperor mode"

start on runlevel [2345]
stop on runlevel [!2345]

接下来,我们需要指定运行该进程的用户和组。 我们将使用我们的普通用户帐户,因为它拥有我们所有的项目文件。 对于我们的组,我们需要允许 www-data 组所有权,这是 Nginx 运行的组。 这将允许 Web 服务器与 uWSGI 自由通信,因为我们的 uWSGI 配置赋予了套接字组读写权限。

之后,我们只需要指定要运行的命令即可启动 uWSGI。 我们只需要使用 --emperor 标志并将包含我们的配置文件的目录传递给它:

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 应用程序服务器来处理我们的 web2py 站点。 皇帝模式让我们可以很方便的在这个目录下添加其他项目的配置文件。 它们将被自动处理。

我们现在完成了我们的 Upstart 脚本。 保存并关闭文件。 此时,我们无法启动 uWSGI 服务,因为我们还没有安装 Nginx。 这意味着我们告诉我们的脚本在其下运行的组还不可用。

安装和配置 Nginx 作为反向代理

配置好 uWSGI 并准备就绪后,我们现在可以安装和配置 Nginx 作为我们的反向代理。 这可以从 Ubuntu 的默认存储库下载:

sudo apt-get install nginx

安装 Nginx 后,我们可以继续修改服务器块配置。 我们将使用默认服务器块作为基础,因为它具有我们需要的大部分内容:

sudo nano /etc/nginx/sites-available/default

web2py 应用程序会检测您是使用纯 HTTP 还是使用 SSL 加密进行连接。 因此,我们的文件实际上将包含每个服务器块。 我们将从配置为在端口 80 上运行的服务器块开始。

更改 server_name 以引用您的站点应该可以访问的域名或 IP 地址。 之后,我们将创建一个 location {} 块来匹配静态内容的请求。 基本上,我们希望使用正则表达式来匹配以 /static/ 结尾的请求和前面的路径组件。 我们希望将这些请求映射到 web2py 项目中的 applications 目录。 确保引用用户的主目录和应用名称:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name server_domain_or_IP;

    location ~* /(\w+)/static/ {
        root /home/user/myapp/applications/;
    }

    . . .

之后,我们需要调整 location / {} 块以将请求传递到我们的 uWSGI 套接字。 我们只需要包含用 Nginx 打包的 uWSGI 参数文件,并将请求传递给我们配置的套接字(在我们的 uWSGI .ini 文件中):

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name server_domain_or_IP;

    location ~* /(\w+)/static/ {
        root /home/user/myapp/applications/;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/user/myapp/myapp.sock;
    }
}

这将是我们第一个服务器块所需的全部内容。

在文件的底部,有一个注释掉的部分,其中包含使用 SSL 提供内容所需的大部分指令。 您可以识别此块,因为它具有 listen 443; 作为第一个指令。 取消注释此块以开始配置它。

首先,再次更改 server_name 以匹配您服务器的域名或 IP 地址。 然后我们可以跳转到 ssl_certificatessl_certificate_key 指令。 我们将暂时将生成的 SSL 证书放入 /etc/nginx/ssl 的目录中,因此请指定该位置的文件路径:

server {
    listen 443;
    server_name server_domain_or_IP;

    root html;
    index index.html index.htm;

    ssl on;
    ssl_certificate /etc/nginx/ssl/myapp.crt;
    ssl_certificate_key /etc/nginx/ssl/myapp.key;

    . . .

ssl_protocols 列表中,删除 SSLv3,因为已发现该协议本身存在漏洞。

然后我们可以跳转到 location / {} 块并将我们在最后一个服务器块中所做的相同的 uWSGI 代理信息:

server {
    listen 443;
    server_name server_domain_or_IP;

    root html;
    index index.html index.htm;

    ssl on;
    ssl_certificate /etc/nginx/ssl/myapp.crt;
    ssl_certificate_key /etc/nginx/ssl/myapp.key;

    ssl_session_timeout 5m;

    #ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/user/myapp/myapp.sock;
    }
}

您现在应该在此文件中配置了两个服务器块。 完成后保存并关闭它。

最后的步骤

接下来,我们需要将 SSL 证书移动到我们指定的目录。 首先创建目录:

sudo mkdir -p /etc/nginx/ssl

现在,将您创建的证书和密钥移动到该目录。 如果您拥有由商业证书颁发机构签署的 SSL 证书,您可以在此处替换证书和相应的密钥,以避免访问者收到不受信任的 SSL 证书警告:

sudo mv ~/myapp/myapp.crt /etc/nginx/ssl
sudo mv ~/myapp/myapp.key /etc/nginx/ssl

修改权限,使非 root 用户无法访问该目录:

sudo chmod 700 /etc/nginx/ssl

现在,检查你的 Nginx 配置文件是否有语法错误:

sudo nginx -t

如果没有报告语法错误,我们可以继续并重新启动 Nginx:

sudo service nginx restart

我们也可以启动我们的 uWSGI 服务:

sudo service uwsgi start

我们需要做的最后一件事是复制应用程序的参数文件,以便在端口 443 上提供连接时可以正确读取该文件。 这包含我们为管理界面配置的密码。 我们只需要将其复制到一个新名称,该名称指示端口 443 而不是端口 8000:

cp ~/myapp/parameters_8000.py ~/myapp/parameters_443.py

这样,您应该能够使用服务器的域名或 IP 地址访问您的服务器。 如果您想登录管理界面,请使用 https

结论

在本指南中,我们设置了一个示例 web2py 项目来练习部署。 我们已经将 uWSGI 配置为我们的应用程序和客户端请求之间的接口。 然后我们在 uWSGI 前面设置 Nginx 以允许 SSL 连接并有效地处理客户端请求。

web2py 项目从一开始就提供了一个可行的 Web 界面,从而简化了站点和 Web 应用程序的开发。 通过利用本文中描述的通用工具链,您可以轻松地为您从单个服务器创建的应用程序提供服务。