为啥在 Alpine Linux 上安装 Pandas 需要很长时间

Posted

技术标签:

【中文标题】为啥在 Alpine Linux 上安装 Pandas 需要很长时间【英文标题】:Why does it take ages to install Pandas on Alpine Linux为什么在 Alpine Linux 上安装 Pandas 需要很长时间 【发布时间】:2018-08-08 19:34:52 【问题描述】:

我注意到使用基本操作系统 Alpine 与 CentOS 或 Debian 在 Docker 容器中安装 Pandas 和 Numpy(它的依赖项)需要更长的时间。我在下面创建了一个小测试来演示时差。除了 Alpine 需要几秒钟来更新和下载构建依赖项以安装 Pandas 和 Numpy 之外,为什么 setup.py 需要比 Debian 安装多 70 倍的时间?

是否有任何方法可以使用 Alpine 作为基础映像来加快安装速度,或者是否有另一个大小与 Alpine 相当的基础映像更适合用于 Pandas 和 Numpy 等软件包?

Dockerfile.debian

FROM python:3.6.4-slim-jessie

RUN pip install pandas

使用 Pandas 和 Numpy 构建 Debian 映像:

[PandasDockerTest] time docker build -t debian-pandas -f Dockerfile.debian . --no-cache
    Sending build context to Docker daemon  3.072kB
    Step 1/2 : FROM python:3.6.4-slim-jessie
     ---> 43431c5410f3
    Step 2/2 : RUN pip install pandas
     ---> Running in 2e4c030f8051
    Collecting pandas
      Downloading pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl (26.2MB)
    Collecting numpy>=1.9.0 (from pandas)
      Downloading numpy-1.14.1-cp36-cp36m-manylinux1_x86_64.whl (12.2MB)
    Collecting pytz>=2011k (from pandas)
      Downloading pytz-2018.3-py2.py3-none-any.whl (509kB)
    Collecting python-dateutil>=2 (from pandas)
      Downloading python_dateutil-2.6.1-py2.py3-none-any.whl (194kB)
    Collecting six>=1.5 (from python-dateutil>=2->pandas)
      Downloading six-1.11.0-py2.py3-none-any.whl
    Installing collected packages: numpy, pytz, six, python-dateutil, pandas
    Successfully installed numpy-1.14.1 pandas-0.22.0 python-dateutil-2.6.1 pytz-2018.3 six-1.11.0
    Removing intermediate container 2e4c030f8051
     ---> a71e1c314897
    Successfully built a71e1c314897
    Successfully tagged debian-pandas:latest
    docker build -t debian-pandas -f Dockerfile.debian . --no-cache  0.07s user 0.06s system 0% cpu 13.605 total

Dockerfile.alpine

FROM python:3.6.4-alpine3.7

RUN apk --update add --no-cache g++

RUN pip install pandas

使用 Pandas 和 Numpy 构建 Alpine 映像:

[PandasDockerTest] time docker build -t alpine-pandas -f Dockerfile.alpine . --no-cache
Sending build context to Docker daemon   16.9kB
Step 1/3 : FROM python:3.6.4-alpine3.7
 ---> 4b00a94b6f26
Step 2/3 : RUN apk --update add --no-cache g++
 ---> Running in 4b0c32551e3f
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
(1/17) Upgrading musl (1.1.18-r2 -> 1.1.18-r3)
(2/17) Installing libgcc (6.4.0-r5)
(3/17) Installing libstdc++ (6.4.0-r5)
(4/17) Installing binutils-libs (2.28-r3)
(5/17) Installing binutils (2.28-r3)
(6/17) Installing gmp (6.1.2-r1)
(7/17) Installing isl (0.18-r0)
(8/17) Installing libgomp (6.4.0-r5)
(9/17) Installing libatomic (6.4.0-r5)
(10/17) Installing pkgconf (1.3.10-r0)
(11/17) Installing mpfr3 (3.1.5-r1)
(12/17) Installing mpc1 (1.0.3-r1)
(13/17) Installing gcc (6.4.0-r5)
(14/17) Installing musl-dev (1.1.18-r3)
(15/17) Installing libc-dev (0.7.1-r0)
(16/17) Installing g++ (6.4.0-r5)
(17/17) Upgrading musl-utils (1.1.18-r2 -> 1.1.18-r3)
Executing busybox-1.27.2-r7.trigger
OK: 184 MiB in 50 packages
Removing intermediate container 4b0c32551e3f
 ---> be26c3bf4e42
Step 3/3 : RUN pip install pandas
 ---> Running in 36f6024e5e2d
Collecting pandas
  Downloading pandas-0.22.0.tar.gz (11.3MB)
Collecting python-dateutil>=2 (from pandas)
  Downloading python_dateutil-2.6.1-py2.py3-none-any.whl (194kB)
Collecting pytz>=2011k (from pandas)
  Downloading pytz-2018.3-py2.py3-none-any.whl (509kB)
Collecting numpy>=1.9.0 (from pandas)
  Downloading numpy-1.14.1.zip (4.9MB)
Collecting six>=1.5 (from python-dateutil>=2->pandas)
  Downloading six-1.11.0-py2.py3-none-any.whl
Building wheels for collected packages: pandas, numpy
  Running setup.py bdist_wheel for pandas: started
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/e8/ed/46/0596b51014f3cc49259e52dff9824e1c6fe352048a2656fc92
  Running setup.py bdist_wheel for numpy: started
  Running setup.py bdist_wheel for numpy: still running...
  Running setup.py bdist_wheel for numpy: still running...
  Running setup.py bdist_wheel for numpy: still running...
  Running setup.py bdist_wheel for numpy: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/9d/cd/e1/4d418b16ea662e512349ef193ed9d9ff473af715110798c984
Successfully built pandas numpy
Installing collected packages: six, python-dateutil, pytz, numpy, pandas
Successfully installed numpy-1.14.1 pandas-0.22.0 python-dateutil-2.6.1 pytz-2018.3 six-1.11.0
Removing intermediate container 36f6024e5e2d
 ---> a93c59e6a106
Successfully built a93c59e6a106
Successfully tagged alpine-pandas:latest
docker build -t alpine-pandas -f Dockerfile.alpine . --no-cache  0.54s user 0.33s system 0% cpu 16:08.47 total

【问题讨论】:

.apk 现在可用,因此零需要从源代码构建 - pkgs.alpinelinux.org/packages?name=*pandas&branch=edge @jtlz2,pandas 在 Alpine 的分支边缘不可用。真可惜…… @fccoelho 现在又可以使用了! 我尝试了几个 cmets 的建议,但每当我将它添加到 alpine 时,我仍然最终尝试构建 pandas。我做了一些挖掘,发现(1)pandas 没有正式打包在apk 中,可能不会很快出现,但是,(2)pandas 作为社区支持的包提供,它安装了一个预编译的二进制文件/usr/lib 并且不需要您编译它。有关更多信息,请参阅我的回答:***.com/a/63839294/6689725 python:3.7-stretch 图像为我工作 【参考方案1】:

在这种情况下,alpine 不是最好的解决方案,将 alpine 更改为 slim:

FROM python:3.8.3-alpine

改成这样:

FROM python:3.8.3-slim

在我的情况下,这个小改动就解决了。

【讨论】:

【参考方案2】:

只是将其中一些答案整合到一个答案中,并添加一个我认为遗漏的细节。某些 python 库,特别是优化的数学和数据库库,在 alpine 上构建需要这么长时间的原因是因为这些库的 pip 轮包括从 c/c++ 预编译并链接到 gnu-libc (glibc) 的二进制文件,这是一组常见的 c 标准库。 Debian、Fedora、CentOS 都(通常)使用glibc,但 alpine 为了保持轻量级,使用musl-libc。在 glibc 系统上构建的 c/c++ 二进制文件将无法在没有 glibc 的系统上运行,musl 也是如此。

Pip 首先查找具有正确二进制文件的***,如果找不到,它会尝试从 c/c++ 源代码编译二进制文件并将它们与 musl 链接。在许多情况下,除非您拥有来自python3-dev 的python 标头或构建像make 这样的工具,否则这甚至都行不通。

现在有一线希望,正如其他人所提到的,社区提供了带有适当二进制文件的 apk 包,使用这些包将节省您构建二进制文件的(有时是冗长的)过程。

事实上,您可以在 alpine 上从纯 python .whl 安装,但是在撰写本文时,manylinux 不支持 alpine 的二进制分发,因为 musl/gnu 问题。

【讨论】:

【参考方案3】:

pandas 被认为是社区支持的软件包,因此指向 edge/testing 的答案将不起作用,因为 Alpine 并未正式支持 pandas 作为核心软件包(它仍然有效,只是核心 Alpine 不支持开发人员)。

试试这个 Dockerfile:

FROM python:3.8-alpine
RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
&& apk add py3-pandas@community
ENV PYTHONPATH="/usr/lib/python3.8/site-packages"

这也适用于香草 Alpine 图像,使用 FROM alpine:3.12


更新:感谢@cegprakash 提出了有关如何使用此设置的问题,当您在容器中还有一个必须满足的requirements.txt 文件时。

我在 Dockerfile sn-p 中添加了一行,以将 PYTHONPATH 变量导出到容器运行时。如果你这样做了,pandasnumpy 是否包含在需求文件中都没有关系(只要它们与通过 apk 安装的版本相同)。

需要这样做的原因是apk/usr/lib 下安装了py3-pands@community 包,但该位置不在pip 在安装新包之前检查的默认PYTHONPATH 上。如果我们不包括此步骤来添加它,pippython 将找不到包,pip 将尝试下载并安装在/usr/local 下,这是我们试图避免的。

鉴于我们真的想确保 pip 不会尝试安装 pandas,我建议包含 pandasnumpyrequirements.txt 文件中,如果您已经使用上述方法使用apk 安装了它们。事情会按预期进行只是一点额外的保险。

【讨论】:

我们应该在 requirements.txt 中包含 pandas 和 numpy 还是不需要? @cegprakash 如果您的requirements.txt 将被复制到一个docker 容器中,其中apk add py3-pandas@community 在创建映像时已经通过Dockerfile 指令运行,那么不,没有必要。我用一些额外的解释修改了我的答案,我认为这些解释会更彻底地回答你的问题。谢谢你提出来:)【参考方案4】:

回答:截至 2020 年 3 月 9 日,对于 Python 3,它仍然没有!

这是一个完整的工作 Dockerfile:

FROM python:3.7-alpine
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk add --update --no-cache py3-numpy py3-pandas@testing

构建对确切的 python 和 alpine 版本号非常敏感 - 弄错这些似乎会引发 Max Levy 的错误so:libpython3.7m.so.1.0 (missing) - 但以上内容现在对我有用。

我更新后的 Dockerfile 可在 https://gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b 获得


[早期更新:]

回答:不是!

在任何 Alpine Dockerfile 中,您都可以简单地做*

RUN apk add py2-numpy@community py2-scipy@community py-pandas@edge

这是因为numpyscipy 和现在的pandas 都可以在alpine 上预构建:

https://pkgs.alpinelinux.org/packages?name=*numpy

https://pkgs.alpinelinux.org/packages?name=*scipy&branch=edge

https://pkgs.alpinelinux.org/packages?name=*pandas&branch=edge

避免每次都重新构建或使用 Docker 层的一种方法是使用预构建的原生 Alpine Linux/.apk 包,例如

https://github.com/sgerrand/alpine-pkg-py-pandas

https://github.com/nbgallery/apks

您可以一次构建这些.apks,然后在您喜欢的 Dockerfile 中的任何位置使用它们 :)

这也让您不必在事前将所有其他内容烘焙到 Docker 映像中 - 即可以灵活地预先构建您喜欢的任何 Docker 映像。

PS 我已经在https://gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b 放置了一个 Dockerfile 存根,它大致显示了如何构建映像。其中包括重要步骤 (*):

RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN apk update
RUN apk add --update --no-cache libgfortran

【讨论】:

看起来它最近被删除了? pkgs.alpinelinux.org/package/edge/testing/x86/py-pandas @ChrisWedgwood 他们正在积极努力 - 请参阅github.com/alpinelinux/aports/pull/6330 @ChrisWedgwood 再次工作,呸! @Kitwradr 得到它的工作 - 查看更新的答案 - 你还需要 Alpine >= 3.8 来获取 scipy - 可能还有 numpy - 需要的 libgfortran。 @xristian Do ***.com/questions/14295680/… , leemendelowitz.github.io/blog/… , bic-berkeley.github.io/psych-214-fall-2016/sys_path.html 帮助?【参考方案5】:

alpine 安装 pandas 需要很多时间,而且图像大小也很大。我尝试了 python:3.8-slim-buster 版本的 python 基础映像。图像构建速度非常快,与 alpine python docker image 相比,图像大小不到一半

https://github.com/dguyhasnoname/k8s-cluster-checker/blob/master/Dockerfile

【讨论】:

【参考方案6】:

这对我有用:

FROM python:3.8-alpine
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk add --update --no-cache py3-numpy py3-pandas@testing
ENV PYTHONPATH=/usr/lib/python3.8/site-packages

COPY . /app
WORKDIR /app

RUN pip install -r requirements.txt

EXPOSE 5003 
ENTRYPOINT [ "python" ] 
CMD [ "app.py" ]

这里的大部分代码来自同一线程的jtlz2 和另一个线程的Faylixe 的答案。

事实证明,在 Alpine 存储库 py3-numpy 中可以找到更轻的 pandas 版本,但它并没有安装在 Python 默认读取导入的相同文件路径中。因此您需要添加ENV。还要注意 alpine 版本。

【讨论】:

【参考方案7】:

注意 看看@jtlz2 回答 latest update

过时

因此,py3-pandas 和 py3-numpy 软件包已移至测试 alpine 存储库,因此,您可以通过将以下行添加到 Dockerfile 中来下载它:

RUN echo "http://dl-8.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
  && apk update \
  && apk add py3-numpy py3-pandas

希望对某人有所帮助!

Alpine 包链接: - py3-pandas - py3-numpy

Alpine 存储库docks info.

【讨论】:

这对我有用!感谢您提供更新的答案! 已在我的回答中修复 @jtlz2 很酷,谢谢,但是我移到了 debian buster 而不是 alpine 并且没有尝试使用 alpine 再次安装它,但无论如何,感谢您的回复,也修复了我的答案 请注意 py3-pandas 不适用于 3.11.x,截至我撰写此评论时,它仅在“边缘”版本中。编辑:显然它在上面的帖子中说,我刚才错过了那个参考,对不起。【参考方案8】:

这里是真正的诚实建议,切换到基于 Debian 的映像,然后您的所有问题都会消失。

用于 python 应用程序的 Alpine 不能很好地工作。

这是我的dockerfile 的示例:

FROM python:3.7.6-buster

RUN pip install pandas==1.0.0
RUN pip install sklearn
RUN pip install Django==3.0.2
RUN pip install cx_Oracle==7.3.0
RUN pip install excel
RUN pip install djangorestframework==3.11.0

python:3.7.6-buster 在这种情况下更合适,此外,您不需要任何额外的操作系统依赖。

关注一篇有用的最新文章:https://pythonspeed.com/articles/alpine-docker-python/:

不要将 Alpine Linux 用于 Python 图像 除非您想要大大降低构建时间、更大的映像、更多的工作以及潜在的隐蔽错误,否则您将希望避免将 Alpine Linux 作为基础映像。有关您应该使用什么的一些建议,请参阅我关于选择良好基础映像的文章。

【讨论】:

您可以减少映像中的层数,即 RUN pip install && pip install 等等,而不是使用一组 RUN 命令。它会影响您的构建性能:) 您也可以使用pip --no-cache 来减少更多占用空间。您真正应该做的只是将它们逐行放入requirements.txt 文件和pip install --no-cache -r requirements.txt【参考方案9】:

基于 Debian 的映像仅使用 python pip 来安装 .whl 格式的软件包:

  Downloading pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl (26.2MB)
  Downloading numpy-1.14.1-cp36-cp36m-manylinux1_x86_64.whl (12.2MB)

WHL 格式被开发为一种安装 Python 软件的更快、更可靠的方法,而不是每次都从源代码重新构建。 WHL 文件只需移动到要安装的目标系统上的正确位置,而源代码分发版则需要在安装前执行构建步骤。

基于 Alpine 平台的图像不支持***包 pandasnumpy。这就是为什么我们在构建过程中使用python pip 安装它们时,总是从 alpine 中的源文件编译它们:

  Downloading pandas-0.22.0.tar.gz (11.3MB)
  Downloading numpy-1.14.1.zip (4.9MB)

在镜像构建过程中,我们可以看到容器内部如下:

/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 /bin/sh -c pip install pandas
    7 root       0:04 pip /usr/local/bin/python /usr/local/bin/pip install pandas
   21 root       0:07 /usr/local/bin/python -c import setuptools, tokenize;__file__='/tmp/pip-build-en29h0ak/pandas/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n
  496 root       0:00 sh
  660 root       0:00 /bin/sh -c gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DTHREAD_STACK_SIZE=0x100000 -fPIC -Ibuild/src.linux-x86_64-3.6/numpy/core/src/pri
  661 root       0:00 gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DTHREAD_STACK_SIZE=0x100000 -fPIC -Ibuild/src.linux-x86_64-3.6/numpy/core/src/private -Inump
  662 root       0:00 /usr/libexec/gcc/x86_64-alpine-linux-musl/6.4.0/cc1 -quiet -I build/src.linux-x86_64-3.6/numpy/core/src/private -I numpy/core/include -I build/src.linux-x86_64-3.6/numpy/core/includ
  663 root       0:00 ps aux

如果我们稍微修改Dockerfile

FROM python:3.6.4-alpine3.7
RUN apk add --no-cache g++ wget
RUN wget https://pypi.python.org/packages/da/c6/0936bc5814b429fddb5d6252566fe73a3e40372e6ceaf87de3dec1326f28/pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl
RUN pip install pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl

我们得到以下错误:

Step 4/4 : RUN pip install pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl
 ---> Running in 0faea63e2bda
pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl is not a supported wheel on this platform.
The command '/bin/sh -c pip install pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl' returned a non-zero code: 1

不幸的是,在 Alpine 映像上安装 pandas 的唯一方法是等到构建完成。

当然,如果您想在 CI 中使用带有 pandas 的 Alpine 映像,最好的方法是编译一次,将其推送到任何注册表并将其用作您需要的基础映像。

编辑: 如果您想将 Alpine 映像与 pandas 一起使用,您可以拉取我的 nickgryg/alpine-pandas docker 映像。它是一个在 Alpine 平台上预编译 pandas 的 python 镜像。它应该可以节省您的时间。

【讨论】:

好吧,那太糟糕了。但是,看起来 6、pytz 和 python-dateutil 正在 Alpine 上下载 .whl 包。这是否意味着它可以为 pandas 和 numpy 为 Alpine 制造***,但目前还没有发生? 不,不可能在 alpine 平台上为 pandasnampy 构建***。那些***不支持它。我在答案中展示了这一点,当试图从它的***包中安装pandas 时。 @Nickolay 是否有一种解决方法可以回收 alpine 上构建然后缓存的 pandas 构建? (这可以在本地某处托管) 之所以这样是因为这些***包含从 c/c++ 构建并与 glibc 链接的二进制文件,但 alpine 没有 glibc,而是使用 musl,这意味着必须编译新的二进制文件并链接到 musl。 我想mac M1也是一样。这需要很长时间

以上是关于为啥在 Alpine Linux 上安装 Pandas 需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章

在 Alpine linux 上安装 ssh-keyscan?

在 Alpine Linux 上安装 Pillow 时没有这样的文件或目录“limits.h”

“找不到 jpeg 的头文件或库文件”在 Alpine Linux 上安装 Pillow

alpine linux怎么安装软件

alpine linux怎么安装文件

Alpine Linux