如何为我的 AWS Elastic Beanstalk 应用程序安装 matplotlib?

How can I install matplotlib for my AWS Elastic Beanstalk application?

我在 AWS Elastic Beanstalk 上部署 matplotlib 时遇到了麻烦。 I gather that my issue comes from some dependencies and the way that EB deploys packages installed with PIP, and have attempted to follow the instructions here on SO 解决问题。

我首先尝试按照链接答案中的建议逐步部署,方法是分阶段将 matplotlib 包堆栈的片段添加到我的 requirements.txt 文件中。但这需要 forever(对于每个阶段)并且容易出现故障和超时(这似乎将构建目录留在后面,导致后续软件包安装停滞)。

所以答案末尾随手提到的简单解决方案对我很有吸引力:只需 eb ssh,用

激活 virtialenv
source /opt/python/run/venv/bin/activate

pip install 手动打包。但我也无法让它发挥作用。首先,我经常遇到遗留的构建目录(如上所述)

pip can't proceed with requirement 'xxxx' due to a pre-existing build directory.
 location: /opt/python/run/venv/build/xxxx
This is likely due to a previous installation that failed.
pip is being responsible and not assuming it can delete this.
Please delete it and try again.

但即使删除了这些,我仍然得到

Exception:
Traceback (most recent call last):
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/basecommand.py", line 122, in main
    status = self.run(options, args)
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/commands/install.py", line 278, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/req.py", line 1197, in prepare_files
    do_download,
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/req.py", line 1375, in unpack_url
    self.session,
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/download.py", line 582, in unpack_http_url
    unpack_file(temp_location, location, content_type, link)
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/util.py", line 625, in unpack_file
    untar_file(filename, location)
  File "/opt/python/run/venv/lib/python2.7/site-packages/pip/util.py", line 533, in untar_file
    os.makedirs(location)
  File "/opt/python/run/venv/lib64/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/opt/python/run/venv/build/xxxx'

响应 pip install xxxx(并且 sudo pipsudo: pip: command not found 而失败)。

我该怎么做才能让它在 AWS-EB 上运行?特别是,我需要做什么才能使简单的 SSH+PIP 方法起作用;还是有其他更好的——更简单! — 我应该尝试的方法。


FWIW,我有一个 .ebextensions/software.config

packages:
  yum:
    gcc-c++: []
    gcc-gfortran: []
    python-devel: []
    atlas-sse3-devel: []
    lapack-devel: []
    libpng-devel: []
    freetype-devel: []
    zlib-devel: []

和一个以

结尾的requirements.txt
pytz==2014.10
pyparsing==2.0.3
python-dateutil==2.4.0
nose==1.3.4
six>=1.8.0
mock==1.0.1

numpy==1.9.1

matplotlib==1.4.2

大约 4 小时后,我已经达到了 numpy 的程度(据 pip list 在 EB virtualenv 中报告)。

并且(以防万一)使用 SSH 的用户属于具有策略

的组
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "elasticbeanstalk:*",
        "ec2:*",
        "elasticloadbalancing:*",
        "autoscaling:*",
        "cloudwatch:*",
        "s3:*",
        "sns:*",
        "cloudformation:*",
        "rds:*",
        "sqs:*",
        "iam:PassRole"
      ],
      "Resource": "*"
    }
  ]
}

我使用了许多方法在 Windows 和 Linux 系统上构建和部署 numpy/scipy/matplotlib。我使用了系统提供的包管理器(aptitude、rpm)、第 3 方包管理器(pypm)、Python 包管理器(easy_install、pip)、源版本、使用不同的构建 environments/tools(GCC,还有 Intel MKL、OpenMP)。在这样做的过程中,我 运行 遇到了许多非常烦人的情况,但也了解了很多关于每种方法的优缺点。

我没有使用 Elastic Beanstalk (EB) 的经验,但我有使用 EC2 的经验。我看到您可以通过 SSH 连接到一个实例并四处查看。所以,我在下面的进一步建议是基于

  • 以上经历及
  • 关于 Beanstalk 和 on
  • 或多或少明显的边界条件
  • 您的应用场景,在 SO 和
  • 上的另一个问题中进行了描述
  • 事实上你只想得到东西 运行宁,快

我的建议: 首先不要自己构建这些东西。不要使用点子。如果可能,请尝试使用 Linux 发行版的包管理器,让它为您处理 所需的一切 的安装,只需一个命令(例如 sudo apt-get install python-matplotlib).

缺点:

  • 可能是旧包版本,具体取决于使用的 Linux 发行版
  • 未优化的构建(例如,不是针对 Intel MKL 构建的,或未利用 OpenMP 功能或未使用特殊指令集)

优点:

  • 下载速度很快,因为包很可能缓存在您的机器附近
  • 它安装很快(这些包是预构建的,不涉及编译)
  • 很好用

所以,我希望您可以在这些机器上使用 aptitude 或 rpm 或其他任何东西,并继承分发包维护人员在幕后为您所做的伟大工作。

一旦您对自己的应用程序充满信心并确定了一些瓶颈或问题,您可能有理由使用 更新的 版本的 numpy/matplotlib/... 或者您可能有理由通过创建优化构建来获得这些的更快版本。

编辑:概述方法的 EB 相关详细信息

同时我们了解到 EB 默认 运行s Amazon Linux 是基于 Red Hat Enterprise Linux。同样,它使用 yum 作为包管理器并且包采用 RPM 格式。

Amazon 提供有关可用包的文档。在 Amazon Linux 2014.09 中,这些包可用:http://aws.amazon.com/de/amazon-linux-ami/2014.09-packages/

在此列表中,我们找到

  • numpy-1.7.2
  • python-matplotlib-0.99.1.2

这个版本的 matplotlib 很旧,根据 changelog 它是从 2009 年 9 月开始的:“2009-09-21 标记为发布 0.99.1”。

我没想到它 这么 旧,但它可能足以满足您的需求。所以我们继续我们的计划(但我理解这是否是一个障碍)。

现在,我们 have learned 系统 Python 和 EB Python 彼此隔离。这并不意味着 EB Python 无法访问系统 Python 站点包。我们只需要它来告诉我们。一个简单而干净的方法是为 EB Python 应该可以访问的包设置一个适当的目录结构,并通过 sys.path.[=36 将该目录传递给 EB Python =]

显然,我们需要自定义 EB 容器的引导阶段。此处记录了可用的工具:http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html

显然,我们想利用 packages 方法,并告诉 EB 通过 yum 安装 numpypython-matplotlib 包。所以相应的配置文件部分应该包含:

 packages:  
  yum:  
   numpy: []  
   python-matplotlib: []  

可能没有必要明确提及 numpy,它可能是 python-matplotlib 的依赖项。

此外,我们需要利用 commands 部分:

You can use the commands key to execute commands on the EC2 instance. The commands are processed in alphabetical order by name, and they run before the application and web server are set up and the application version file is extracted.

以下三个命令创建上述目录,并设置指向numpy/mpl安装路径的符号链接(希望这些路径在执行这些命令时可用):

commands:
  00-create-dir:
    command: "mkdir -p /opt/py26-selected-site-packages"
  01-link-numpy:
    command: "ln -s /usr/lib64/python2.6/site-packages/numpy /opt/py26-selected-site-packages/numpy"
  02-link-mpl:
    command: "ln -s /usr/lib64/python2.6/site-packages/matplotlib /opt/py26-selected-site-packages/matplotlib"

两个不确定因素:AWS 文档未阐明 packagescommands 执行之前处理。你得试试。如果它不起作用,请使用 container_commands。其次,这只是一个有根据的猜测,安装 python-matplotlib 后 /usr/lib64/python2.6/site-packages/matplotlib 可用。它应该安装到这个地方,但它可能会在其他地方结束。需要测试。 Numpy 应该在从 this 文章推断的指定位置结束。

[来自 SEB 的更新] AWS 文档说 "The cfn-init helper script processes these configuration sections in the following order: packages, groups, users, sources, files, commands, and then services." http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html

所以,你的方法是安全的 [/更新]

正如对此答案的评论中所指出的,关键的一步是告诉您的 Python 应用到哪里寻找包。在尝试导入之前直接修改 sys.path 是控制此问题的可靠方法。以下代码将我们的特殊目录添加到 Python 查找包的目录选择中,然后尝试导入 matplotlib:

sys.path.append("/opt/py26-selected-site-packages")
from matplotlib import pyplot

sys.path 中的顺序定义了优先级,因此如果其他目录中有任何其他 matplotlib 或 numpy 包可用,

可能是更好的主意
sys.path.insert(0, "/opt/py26-selected-site-packages")

但是,如果我们的整个方法都经过深思熟虑,则没有必要这样做。

添加到 Jan-Philip 答案:

AWS Elastic Beanstalk 使用 Amazon Linux 发行版(.Net 环境除外)。 Amazon Linux 使用 yum 包管理器。 MatPlotLib 可在亚马逊的软件存储库中找到。

[ec2-user@ip-1-1-1-174 ~]$ yum list | grep matplot
python-matplotlib.x86_64            0.99.1.2-1.6.amzn1              amzn-main

如果这个版本是您的应用程序所需的版本,我会尝试简单地修改您的 .ebextensions/software.config 文件并将包添加到它的 yum 部分:

packages:
  yum:
    python-matplotlib: [] 
    python-devel: []
    atlas-sse3-devel: []
    lapack-devel: []
    libpng-devel: []
    freetype-devel: []
    zlib-devel: []

关于 AWS Elastic BeansTalk 和 SSH 的最后说明。

虽然 Amazon 为您提供了通过 SSH 连接到 Elastic Beanstalk 实例的可能性,但您应该仅将这种可能性用于调试目的,以了解您的应用程序失败或未按建议安装的原因。

除此之外,您的部署必须是 100% 自动的。当 Elastic Beanstalk(准确地说是 Auto Scaling)根据您的应用程序工作负载扩展您的基础架构(添加更多实例)或缩减它(终止实例)时,您所有的手动配置都将丢失。

最佳做法是不要在您的生产环境中安装 SSH 密钥,这会进一步减少攻击面。

我回答这个问题可能有点晚了,但随着 AWS 和许多云服务提供商正在转向 Docker 并考虑到您尚未指定平台。我有一个快速解决你的问题的方法:

  1. 使用通用 docker 平台。
  2. 我创建了一些预装了 Python、Numpy、Scipy 和 Matplotlib 的图像,因此您可以直接拉取并使用一行代码开始使用它们。

Python 2.7(这个也有你为 numpy 和 matplotlib 指定的版本)

sudo docker pull chuseuiti/pynuscimat2.7

Python3.4

sudo docker pull chuseuiti/pynusci

但是您可以创建自己的图像或修改现有图像。

如果您想自动化您的实例,您可以将一个 Docker 包含图像定义的文件传递给 AWS。

提示,如果你不知道docker:

需要先登录才能拉取:

sudo docker login

拉取镜像后,您可以使用以下代码生成并在从镜像创建的容器中工作:

 sudo docker run -i -t chuseuiti/pynuscimat2.7 bash

PS。至少对于免费层 AWS 总是抱怨 运行 与 scipy 和 matplotlib 超时,安装它们需要太多时间,这就是我使用此选项的原因。