Docker和Python虚拟环境有什么区别?

194

根据我对Docker的了解,它是一个用于虚拟环境的工具。在他们的术语中,这被称为“容器化”。这或多或少是Python的virtualenv所做的。然而,你可以在Docker中使用virtualenv。那么,这是在虚拟环境中的虚拟环境吗?我不确定这该如何运作,能否有人请澄清一下?


64
这是一个好问题,但很可能会因为不属于主题而被关闭。virtualenv并不是真正的隔离,它使用路径和符号链接来实现贫穷人的隔离 - 你仍然处于自己的操作系统中。Docker提供了更多的隔离,但没有完全虚拟机那么多。你可以把容器看作是虚拟机(笨重、昂贵)和virtualenv(轻便、廉价)之间的中间地带。在容器内创建virtualenv没有太多意义,因为docker已经提供了隔离,这样做没有太多的意义。 - wim
6个回答

225

虚拟环境只封装 Python 依赖项。Docker 容器则封装整个操作系统。

使用 Python 虚拟环境,您可以轻松切换 Python 版本和依赖项,但只能在主机操作系统中运行。

使用 Docker 镜像,您可以更换整个操作系统 - 在 Ubuntu、Debian、Alpine 甚至 Windows Server Core 上安装和运行 Python。

有许多 Docker 镜像 包含各种 OS 和 Python 版本的组合,可以随时从任何已安装 Docker 的系统上下载并使用。


2
此外,谷歌还提供了“几种流行的编程语言”(包括Python)的distroless镜像,这些镜像“仅包含编程语言运行时”-来自ArchWiki/Docker - muthuh
对于封装不仅限于 Python 依赖项(如 Python 本身)的虚拟环境,请查看 nixpkgs/nix-shell(在 macOS 上也适用)。使用卷进行开发/热重载代码的 macOS Docker 很慢,因为在 macOS 上,Docker 运行在 VM 中 - 需要将文件/文件系统事件从 macOS 文件系统转换为 ext4 或类似格式。 - Tobias Bergkvist
1
如果Docker替换整个操作系统,那么它不就变成了虚拟机吗? - MaazKhan47
@MaazKhan47 不是的,虚拟机模拟硬件(CPU、内存),并将磁盘存储和网络流量从模拟内存重定向到文件和模拟端口。Docker直接使用底层硬件来提供这些资源。存储和网络端口映射到容器中,内存专门用于容器。 - dan

39

Python虚拟环境只会"容器化"Python运行时即Python解释器和Python库,而Docker隔离整个系统(整个文件系统、所有用户空间库、网络接口)。因此,Docker比虚拟环境更接近虚拟机。


2
在Docker容器内创建虚拟环境是否有益处,考虑到该容器仅提供Flask Web应用程序服务? - thanos.a

19

除了上面的内容,还有一个将 Docker 和 venv 结合的情况:某些操作系统已安装 Python 以提供“接近操作系统”的应用程序,例如据我所知,在 Debian(及其衍生版)上是通过 apt 安装的。Python venv 可以使开发人员在不影响操作系统自带的 Python 的情况下,运行需要其他解释器版本的 Python 应用程序。现在,由于 Docker 如上所述“隔离整个操作系统”,同样适用于 Docker 镜像。因此,在我看来,如果需要/想使用 Docker 镜像,则最好的做法是在 Docker 镜像内为您的 Python 应用程序创建一个 venv。


6
这会减慢响应时间吗(存在两个虚拟化层级)? - Andy Swift
5
Python虚拟环境会改变Python环境,但它不会虚拟化Python解释器的执行。只有在使用虚拟机(Docker Machine)执行Docker容器时,才会对容器进行虚拟化。 - Morten
我仍然认为在操作系统中安装Docker对我来说会很繁琐,通常我会使用Shell语言编写项目中与Python无关的所有依赖项,并通过SSH自动执行它们,比如在生产环境中。 - Alex Hurtado
需要不同的解释器版本-这是错误的。venv与创建它的操作系统解释器版本相同。 - OneCricketeer

2
"

虚拟环境是一个自包含的目录树,其中包含特定版本的Python安装程序以及一些额外的包。

Docker容器提供了更高级别的抽象/隔离,它可以拥有自己的“进程空间、文件系统、网络空间、IPC空间等”。

"

2
虚拟环境是一组依赖项的集成,确保一个或多个应用程序可以无缝地协同工作。它为感兴趣的应用程序提供了一组运行时保证。虚拟环境将给定的依赖项集合与系统应用程序隔离开来,允许用户和开发人员拥有尽可能多的应用程序上下文。
特别是,Python虚拟环境旨在将特定版本的Python绑定的特定依赖项集合与系统Python隔离开来。通过这种方式,用户可以拥有多个系统Python版本,每个版本都可以有相应的虚拟环境集合,每个集合具有独立的依赖项。因为Python虚拟环境仅适用于Python,所以安装在系统中的任何非Python应用程序都将以完全相同的方式被所有Python虚拟环境看到。具体而言,可以安装Python3.7到Python3.11作为系统Python,同时拥有四个Python3.10虚拟环境(venv1-venv4),每个虚拟环境都有不同版本的requests库。venv2中的应用程序只能使用该虚拟环境中的特定版本的requests,不能使用其他版本。
另一方面,Anaconda虚拟环境将依赖项的集合扩展到Python之外,包括几乎任何应用程序。这意味着它们可以包括系统应用程序(非Python)以及完全独立于系统应用程序的全部底层库集合。例如,在Apple Silicon上使用HDF5库的Anaconda虚拟环境将在虚拟环境内完整构建适用于Apple Silicon的HDF5。在此Anaconda虚拟环境之外运行的任何应用程序都将完全不知道HDF5的存在。
Docker或容器是一种完全不同的技术,仅适用于Linux机器,在其中应用程序通过名称空间实现了相互隔离。每个容器只提供一个虚拟进程空间,只能由该容器中的应用程序访问,并由容器运行时(如Docker、Containerd、podman等)进行外部管理。因此,可以有包含Anaconda虚拟环境的容器。容器运行时也可以移植到非Linux操作系统,但仍需要Linux内核来启用底层进程名称空间。这就是为什么Docker可以在Windows和macOS上运行,尽管两者都不本地支持进程名称空间。
总之,虚拟化主要有两种类型:
  • 应用程序依赖虚拟化(Python和Anaconda虚拟环境),可以视为“静态”虚拟化,以及
  • 通过容器进行过程虚拟化,可以视为“动态”虚拟化。

但是,我可能是错的...


-2

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

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