gpt4 book ai didi

python - 如何更好地利用缓存进行 pip 安装

转载 作者:太空宇宙 更新时间:2023-11-03 20:18:02 25 4
gpt4 key购买 nike

通常,我会创建一个 Dockerfile 来安装单个软件,类似于 pip3 install apache-airflow .

当这个软件很复杂时,它会依赖几十个Python包。例如,上面的行提示 pip 收集 ~20 个依赖包。每个包都有自己的依赖项,所以最终我可以安装 100 个或更多的 python 包。没关系,如果开发人员需要这些依赖项,我无能为力。

但是,有时此过程会因为某些必备的 Linux 程序而中断,例如 gcc ,在调用 pip 之前未安装。在像 Alpine 这样带有非标准软件包的最小发行版上,情况会变得更糟。我会遇到这样的情况:

  • 请求安装单个程序(例如airflow)
  • Pip 提供了约 100 个必备 Python 包的列表
  • 全部下载
  • 开始逐一安装
  • 程序包 71/100 出现编译器错误,一切都失败

然后我必须返回,尝试添加一些 alpine 软件包来处理编译器错误,然后重试(看看现在软件包 74 是否会由于不同编译器错误而失败) 。然而,每次这样的试验都需要很长时间,因为docker build将重新下载所有先决条件并重新安装前 70 个不会出现错误的软件包。 Docker 构建缓存也没有被使用:从技术上讲,这整个漫长的过程就是一个命令,因此它只创建一个缓存镜像,并且只有在它实际成功时才创建。另外,添加 RUN apk get之前pip3 install无论如何都会导致整个事情从头开始重新构建。

例如,考虑到问题出在软件包 #71 上,当我对 Dockerfile 进行故障排除时,浪费大量时间重新下载所有 100 个软件包并重新构建前 70 个软件包是没有意义的。在这种情况下如何更有效地利用缓存?

我当前的“解决方案”是手动浏览pip install输出,编译它获得的所有依赖项的列表,然后将它们转换为单独的 RUN pip3 install PACKAGE_NAME我的 Dockerfile 中的命令。这样,每个包安装尝试都会被单独缓存。然而,这似乎不是 Dockerfile 语法的一个很好的使用方式。有更好的办法吗?

最佳答案

这里有三个建议。这里重要的是你不需要第一次就做到完美;因此,将问题分解为更小的部分并进行一些实验。

第一个普遍有用的建议是在开发过程中分解 RUN 语句。典型的 Docker 风格是拥有少量的大型 RUN 语句

RUN apk add ... \
&& pip3 install -r requirements.txt \
&& ... \
&& apk del ...

但是,当您开发此内容并尝试解决问题时,将其分解为较小的语句可能会有所帮助

RUN apk add ...
# If the next line breaks, you'll get caching on the previous line
RUN pip3 install -r requirements.txt

对此进行调试并稍后将它们组合起来。

当您运行docker build时,它会在每个步骤之后打印出行,例如

 ---> e38ccc1e7f56

每一行都是一个有效的 Docker 镜像 ID,您可以运行

docker run --rm -it e38ccc1e7f56 sh

获取该步骤输出的调试 shell。对于第二个技巧,您可以强制 RUN 命令成功

RUN pip3 install -r requirements.txt || true

这将始终“成功”,因此您将获得有效的 Docker 镜像。这将处于您尝试调试的状态:软件包安装失败,但 Dockerfile 中到目前为止的所有内容都已运行,并且 pip 已经下载了软件包。

现在,由于构建损坏,您在一次性容器中拥有了一个交互式 shell。您可以在这里非常自由地进行实验。尝试再次运行pip3 install;好 pip 吗? apk 是否添加了一些特定的开发包帮助或编译器?这里重要的第三个技巧是在文本编辑器中打开 Dockerfile 时进行此实验:您可能已经有一个有效的 apk add 行,您可以轻松地向其中添加更多包,因此每次您需要另一个包来进一步安装 pip3,只需将其添加到您的 Dockerfile 中即可。

您对每次安装一个包的 pip3 的想法也是本着这一思路。它是最佳的生产 Dockerfile 吗?不,但是您可以更轻松地调试单个软件包未安装的原因。

一旦一切正常,您应该删除多余的 || true 位,将您的 RUN 行组合在一起,依此类推。将其视为准备发货之前的最后清理步骤。

<小时/>

较新的 Docker 有 a non-default alternate build engine支持some experimental build syntax 。那有a specific RUN variant explicitly supporting cache directories您也许可以使用它来缓存您的 .pip 目录。我还没有看到它的很多用途,部分原因是它被如此明显地标记为“实验性”。

关于python - 如何更好地利用缓存进行 pip 安装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58331150/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com