如何将Python Flask应用部署到运行在亚马逊Linux EC2实例上的Apache(Httpd)?

8

我在这里遇到了很大的困难。我开发了一个简单的Python Flask REST API。该API在我的本地开发环境(Mac OS X)中运行良好,并且在我的EC2实例上通过控制台直接执行时也可以正常运行。

我想将此服务移植到生产环境,并希望在EC2实例上运行Apache进行托管。这就是我一直遇到问题的地方,我似乎无法解决配置和错误问题。我已经在网上研究了几篇文章和问题,但都没有能够帮助我。

我希望有人能够提供逐步说明,告诉我如何将我的服务部署到在Amazon Linux EC2实例上运行的Apache后面。

以下是我所采取的步骤:

  1. 启动基本的Amazon Linux EC2实例。
  2. 对实例应用更新,sudo yum update
  3. 安装Apache和WSIG,sudo yum install httpd24 mod24_wsgi
  4. 启动Apache,sudo service httpd start
  5. 配置Apache自动启动,sudo chkconfig httpd on
  6. 通过访问我的EC2盒子的DNS进行测试。我成功获取了Amazon Linux AMI测试页面。
  7. 按以下方式调整/var/www的权限
    • sudo groupadd www
    • sudo usermod -a -G www ec2-user
    • 登录/注销并确认成员身份,groups
    • sudo chown -R root:www /var/www
    • sudo chmod 2775 /var/www
    • find /var/www -type d -exec sudo chmod 2775 {} \;
    • find /var/www -type f -exec sudo chmod 0664 {} \;
  8. 通过访问我的EC2盒子的DNS进行测试-到目前为止还不错。
现在我知道我的实例正在运行,我想创建两个文件夹来测试和运行我的Python Flask代码。我按照以下步骤操作:
  1. 我创建了两个文件夹,一个用于开发,一个用于生产。
    • /var/www/rest-dev/
    • /var/www/rest-prod/
  2. 我在每个文件夹中设置了虚拟环境并安装了Flask。
    • virtualenv env
    • env/bin/pip install Flask
    • 然后我在每个文件夹中放置了服务的副本。
    • 然后我对app.py设置了权限,chmod a+x app.py
    • 我可以成功执行./app.py并通过访问DNS名称+端口5000来测试服务。它有效。

现在这就是我被绊倒的地方。我的目标是能够访问api.example.com并加载我的服务的根目录。在下面的示例代码中,“Hello, World!”应该简单显示。

我按照这里找到的教程进行了操作,但没有成功。

http://peatiscoding.me/geek-stuff/mod_wsgi-apache-virtualenv/

http://webpy.org/cookbook/mod_wsgi-apache

http://www.jakowicz.com/flask-apache-wsgi/

在执行上述任何一篇文章中的任何步骤后,我会得到一个HTTP错误页面,再也无法加载任何内容,包括默认的Amazon Linux AMI测试页面。以下是我更改的代码和配置片段。我没有更改我的httpd.conf... 我应该吗?可能还有其他几件事我错过了。
请问有人能够详细提供必要的步骤来纠正我的错误吗?
非常感谢!
当我查看HTTPD的error_log时,它列出了像这样的错误:
mod_wsgi (pid=8270): Target WSGI script '/var/www/rest-dev/deploy.wsgi' cannot be loaded as Python module.
mod_wsgi (pid=8270): Exception occurred processing WSGI script '/var/www/rest-dev/deploy.wsgi'.
Traceback (most recent call last):
  File "/var/www/rest-dev/deploy.wsgi", line 16, in <module>
    from app import app as application
  File "/var/www/rest-dev/app.py", line 2, in <module>
    from flask import Flask
ImportError: No module named flask

这是我的deploy.wsgi文件,位于rest-dev文件夹中:

import os
import sys
import site

# Add virtualenv site packages
site.addsitedir(os.path.join(os.path.dirname(__file__),     'env/local/lib64/python2.7/site-packages'))

# Path of execution
sys.path.append('/var/www/rest-dev')

# Fired up virtualenv before include application
activate_env = os.path.expanduser(os.path.join(os.path.dirname(__file__), 'env/bin/activate_this.py'))
execfile(activate_env, dict(__file__=activate_env))

# import my_flask_app as application
from app import app as application

这是我的vhost.conf文件,位于/etc/httpd/conf.d/目录中。

<VirtualHost *:80>
        ServerName api.example.com

        WSGIDaemonProcess webtool user=ec2-user group=www threads=5 home=/var/www/rest-dev/
        WSGIScriptAlias / /var/www/rest-dev/deploy.wsgi

        <directory /var/www/rest-dev>
                WSGIProcessGroup webtool
                WSGIApplicationGroup %{GLOBAL}
                WSGIScriptReloading On
                Order deny,allow
                Allow from all
        </directory>
</VirtualHost>

以下是我参考的 app.py 示例服务代码:

#!env/bin/python
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

如果Apache以root身份启动,则WSGIDaemonProcess指令中的usergroup设置才会生效,但这里可能并不是这样。这意味着所有文件和目录(包括虚拟环境目录!)都需要由Apache用户访问。您确定它们是可访问的吗? - mata
你可以使用 su 命令切换到 apache 用户,然后尝试访问 (sudo su apache -s /bin/bash)。如果无法访问,则可以将目录设置为全局可读 (chmod a+rX venvdir) 或者设置为 apache 组所有并且组可读 (chmod g+rX -R venvdir)... - mata
我执行了 sudo su apache -s /bin/bash,并且我相信它起作用了。提示符已更改为 [apache@ip-123-45-67-89 httpd]$ - K997
现在尝试切换到虚拟环境并查看是否可以访问文件... - mata
抱歉,我可能说得太早了——如果我输入ls,我会得到一个权限被拒绝的错误。pwd 显示我在/var/log/httpd目录下。很抱歉,我对 Linux / Unix 不是很熟悉... - K997
显示剩余3条评论
1个回答

5
原来在我的deploy.wsgi文件中,我引用的是lib64而不是只有lib。所有的网站包都存在于lib中。
更改后并重新启动Apache,我能够从URL成功访问我的服务。

@arun,当你从网页访问时,你使用的是5000端口还是80端口? - nshathish
它可以是您通过Flask app.run定义的任何端口,但通常会避免在测试中使用80端口。 - K997

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接