单独使用Conda与在Docker上结合使用Conda的区别

2,144 阅读6分钟

Docker打包很有用,但做好它并不容易。即使把讨论的范围限制在Python应用程序的生产使用上,要涵盖的细节也是非常多的,以至于我已经写了50多篇关于这个话题的文章,并创造了许多产品来加速打包过程

在一个更好的宇宙中,这些都是不必要的。

因此,虽然Docker通常足够有用,值得这样做,但在某些情况下,你最好完全避免使用Docker。具体来说,Conda提供了Docker的一些好处。虽然Conda肯定有它自己的问题,但单独使用Conda会比在Docker上结合使用Conda涉及的工作要少。

这篇文章将涵盖。

  • 开发环境。
    • Docker打包的好处。
    • 弊端。
    • 为什么Conda可以让你避免这些缺点而仍然有同样的好处。
  • 生产方面,Docker的好处可能会被框架功能和Conda的结合所取代。

用于开发环境的Docker

当你在本地进行软件工作时,在开发过程中,Docker有很多好处。

首先,你可能需要运行额外的服务,比如PostgreSQL;Docker,尤其是Docker Compose,使之变得更加容易。Conda在这方面并没有什么帮助,所以如果这是一个要求,Docker很可能是正确的解决方案。

第二,你可能会有使用多个操作系统的开发者,这引起了一些困难。

  • **每个开发者的运行环境会因为他们的操作系统而不同。**通过在Docker上运行,你可以在同一个操作系统上一致地运行应用程序,无论你的图像是基于什么变体的Linux。
  • **在多个操作系统上一致地安装不同的工具会很困难。**你可能需要一些可用的实用程序。git,black,flake8, 也许是一个编译器。在Linux上,你可能会使用aptdnf 或其他工具,在macOS上,你会需要brew ,而在Windows上,祝你好运,没有一个软件包库看起来那么好。Docker可以让你访问所有这些工具,把它们放在一个Linux镜像中,所以你只需要通过一种方式安装它们。

然而,有一些注意事项:虽然Docker镜像在不同的操作系统中运行一致,但它们并不完全相同,而且这些差异在开发环境中变得更加显著。

  • 当把主机目录挂载为卷时,这是开发环境中常见的情况,在macOS和Windows上,任何写入的文件都将由主机的用户拥有。在Linux上,创建的文件将有一个不同的UID,所以你需要采取措施,以主机用户的UID身份运行容器,如果镜像不是这样设计的,这可能很棘手。
  • 如果你想使用host.docker.internal 来访问在主机上运行的进程,这在Linux中开箱即用是不行的。

Python和Conda:跨平台的逻辑,跨平台的依赖性

如果你正在写一个Python项目,并且你依赖于Conda,特别是Conda-Forge,那么Docker对于开发环境的好处就变得不那么引人注目了。

**当涉及到运行时环境时,Python已经创建了一个相当跨平台的抽象层。**无论是打开文件还是联网,Python API和建立在它们之上的库通常都会抽象出大部分特定平台的细节。

**这对命令行工具(至少是非Python的)、编译器和你可能依赖的本地库没有帮助......但这正是Conda出现的地方。**Conda打包了除标准C库之外的所有东西,从C库到Python解释器到命令行工具到编译器。Conda-Forge有大量的工具、库和一般的软件包可用,为Windows、macOS和Linux预编译。

因此,与其在Windows上使用apt +brew +任何你正在做的事情,你可以有一个统一的打包配置。environment.yml,可以选择conda-lock's multi-OS lock files来保证额外的一致性。它将列出你运行和开发代码所需的所有工具、库、编译器、Python依赖项等等,并在不同的操作系统上一致地安装。不需要Docker!

name: yourapp
channels:
  - conda-forge
dependencies:
  - python=3.9
  - flake8
  - black
  - git
  - compilers

总结一下,对于Python开发环境的用例,下面是你可能会选择Docker的替代品。

Docker用例Docker的替代品
像Postgres这样的服务困难,可能不值得做
一致的运行时间Python的跨平台抽象
跨平台工具的安装Conda

Conda作为生产中的Docker替代品

Conda能否在生产中作为Docker的替代品?

鉴于生产镜像通常只在Linux上运行,跨平台的一致性就变得不那么重要了。但是Docker镜像结合了我们想要的两件事。

  • 一套能在Linux上运行的一致的文件,包括:。
    • 所有的依赖性。
    • 实际的应用程序代码。
  • 启动时要运行的特定命令。

正如我们为开发环境所讨论的那样,通过Conda获得一致的依赖性通常是Docker的合理替代方案。唯一依赖主机操作系统的是glibc,其他的东西几乎都是由Conda打包的。因此,一个钉子式的environment.ymlconda-lock.yml 文件是Docker镜像的一个合理替代方案,因为它具有一致的依赖性。

剩下的就是获取你的应用程序代码,并运行它。

在许多情况下,你用来运行你的代码的框架可以安装Conda包,并将你的代码分发到任何运行环境中,而且还可以控制运行的内容。这意味着你并不真的需要一个Docker镜像。比如说。

所有这些框架都会让你设置什么命令或代码被运行,这取决于它们的抽象级别。

避免使用Docker的一些限制

首先,如果你不使用Docker镜像,那么在输出中记录你所使用的代码的版本就比平时更加重要,这样你就可以在以后重现所有必要的代码。

其次,还有一个启动问题:根据你所使用的框架,你可能需要安装Conda和框架驱动,然后才能开始工作。一个Docker镜像会预装这两样东西,还有你的代码和它的依赖性。因此,即使你的框架直接支持Conda,你可能还是想使用Docker。

第三,根据框架的智能程度,你可能会发现自己在每次运行时都要重复安装Conda包。这是很低效的,即使是使用像Mamba这样更快的安装程序

你并不是什么都需要容器的

无论它们多么有用,容器只是众多解决方案中的一种,在某些情况下,Conda可以给你带来许多好处,而且复杂程度较低。每个工具都有它的优势,几乎每个工具都有替代品,所以至少值得花一点时间考虑你的默认工具是否是最适合的工具。