使用docker部署python,图片太大

时间:2018-10-09 11:15:41

标签: python amazon-web-services docker

我们已经建立了一个大型的Python库,它使用了很多库(numpy,scipy,张量流等),并通过conda环境管理了这些依赖关系。基本上,我们有很多开发人员参与其中,并且任何时候只要有人需要一个新的库来处理他们正在“ conda安装”的库。

现在到现在,我们需要部署一些使用我们的仓库的应用程序。我们正在使用docker进行部署,但发现这些映像确实很大,并且会引起一些问题,例如10 GB以上。但是,每个单独的应用程序仅使用environment.yml中所有依赖项的子集。

有一些简单的策略可以解决这个问题吗?从某种意义上说,我需要了解每个应用程序的依赖关系,但是我不确定如何以自动化方式执行此操作。

这里的任何帮助都会很棒。我对整个AWS,Docker和python部署还是陌生的……我们实际上是一群需要扩展软件的工程师和科学家。我们有一些可行的方法,似乎必须有一种更好的方法。

3 个答案:

答案 0 :(得分:2)

首先查看是否有轻松的方法来缩小映像,例如使用Alpine Linux并非常小心OS软件包管理器安装了什么,并确保仅在真正需要时才安装依赖项或推荐项,以及清理并删除工件(如软件包列表),可能不需要的大物件(如Java)等。

Anaconda / Ubuntu基本映像的大小约为3.5GB,因此,如果大量安装额外的重型第三方软件包,则可以获得高达10GB的存储空间,这并不奇怪。在生产图像处理应用程序中,我通常使用3GB至6GB范围内的Docker图像,而这些尺寸是 我们对容器进行了最优化之后。

对于有关拆分依赖项的问题,您应该为每个不同的应用程序提供其自己的程序包定义,基本上是setup.py脚本和一些其他详细信息,包括在pip和/或环境的requirements.txt混合列表中列出的依赖项。康达(yada)。

如果您在某个文件夹中有项目A /在另一个仓库中有项目B,而在另一个文件夹中有项目B,则希望人们能够轻松地执行诸如pip install <GitHub URL to a version tag of Project A>conda env create -f ProjectB_environment.yml之类的操作,瞧,该应用程序就是已安装。

然后,当您部署特定的应用程序时,让诸如Jenkins之类的CI工具使用FROM行从薄型Alpine /任何容器(仅 )开始为该应用程序构建容器对于该项目的依赖文件 ,而不是其他所有文件,执行conda安装或pip安装。

这还具有以下优点:即使在同一组库中,多个不同的项目也可以声明不同的版本依赖性。也许Project A已准备好升级到最新最好的熊猫版本,但是Project B需要进行一些重构,然后团队才能测试该升级。这样,当CI为Project B构建容器时,它将具有带有一组版本的Python依赖文件,而在Project A的文件夹或源代码存储库中,它可能有所不同。

答案 1 :(得分:1)

有很多方法可以解决此问题:

  1. 精简的docker映像-从一个非常简单的基本映像开始;并分层您的图像。参见best practices for building images

  2. 使用$文件(请确保您pin your versions)指定各个应用程序要求,然后查看specific instructions for conda

  3. “按需”构建和安装;当您进行docker构建时,仅针对特定应用程序安装这些要求,而对每种可能的情况都不会安装一张巨型映像。

答案 2 :(得分:1)

我建议:

  1. 使用标准的Python应用程序包装;您的单个应用程序应该是行为良好的Python程序包,它们声明了自己的依赖项。
  2. 每个应用程序都变成自己的Docker映像并管理自己的依赖项。
  3. 不要试图维护巨大的全依赖基础形象。
  4. 如果开发人员不愿意,则不必使用Docker进行本地开发。

Python对声明其自己的依赖关系的应用程序以及在具有所需库依赖关系的环境中运行应用程序提供了良好的内置支持。您的开发人员应该为他们正在从事的每个项目set up Python virtual environments(或者如果他们更喜欢一个共享的本地开发项目)。有two paths for a Python application to declare its dependencies,每个项目应在其特定于项目的setup.py和/或requirements.txt文件中声明其依赖项。

所有这些都完全独立于Docker。许多人都将Docker用作其核心开发流程的一部分,但是如果您围绕着正确声明其依赖项的软件包保持良好实践,那么这将有助于构建容器并有助于纯粹的本地开发过程。

当您要部署Docker映像时,每个应用程序应具有自己的映像。 Dockerfile应该检入源代码管理,通常在项目的根目录中,与setup.py和/或requirements.txt文件一起。 (这可能是很简单的样板; Docker Hub python image documentation中的示例实际上可以在大多数应用程序中正常工作。)

一个具有所有可能的依赖关系的巨大基础映像将引起问题。实际上,我遇到了千兆字节以上范围的图像和图层的网络错误;从长远来看,当两个应用程序需要同一个库的不兼容版本时,您会遇到麻烦。我会放弃这种方法。

如果要执行诸如从源代码编译numpy之类的操作,则可能需要使用一些通用技巧,例如多阶段构建。您的运行时映像不需要完整的C和FORTRAN工具链,也不需要携带中间的构建工件。在基础层(可能是放在轮子上,也可能是安装包)中构建软件包,然后将其复制到最后一层。